On Thu, Aug 30, 2012 at 9:13 AM, Sven Marnach firstname.lastname@example.org wrote:
I'd usually simply use ``hasattr(a, "__add__")``. This is also what e.g. MutableMapping.update() currently does. The chances that someone accidentally passes in an object that has a callable instance variable called "__add__" seem pretty low, and we don't need to protect against people intentionally trying to break things.
That said, ``hasmethod()`` can be implemented in a quite straight-forward way in pure Python:
def hasmethod(obj, name): return inspect.ismethod(getattr(obj, name, None))
I don't think that's *quite* what Guido is getting at: it's more about exposing the semantics of _PyType_Lookup at the Python level.
There are currently two different ways of approximating that. The one which mimics _PyType_Lookup most closely (by treating proxy types as instances of the proxy type, rather than the target type) is to do "type(x.).attr", "getattr(type(x), 'attr')" or "hasattr(type(x), 'attr')" rather than performing those operations directly on 'x'.
There's an alternative which treats proxy objects as an instance of the *target* type, which is to respect the claimed value of __class__: "x.__class__.attr", "getattr(x.__class__, 'attr')" or "hasattr(x.__class__, 'attr')"
Yet *both* of those alternatives have the problem Guido noted, where they can find metaclass methods that the descriptor protocol would ignore:
class C: pass
c = C() type(c)
_PyType_Lookup is essentially "ordinary attribute lookup, but ignore the instance variables and don't supply the instance to descriptors", or, equivalently, "class attribute lookup, but don't fallback to the metaclass". It's a necessary part of the language semantics, but it's not currently accessible from Python code.
I believe the last time this came up, the main idea being kicked around was a new function in the operator module (e.g. "operator.gettypeattr()") rather than a new builtin.