On Wed, Aug 29, 2012 at 03:48:01PM -0700, Guido van Rossum wrote:
There's a concept that's sometimes useful when explaining behavior of certain Python operations in terms of simpler ones, and it is "does the class of x define a method m?".
This currently cannot expressed using hasattr(): hasattr(x, 'm') might find an instance variable named m, but that is not a method (and there are contexts where they are not interchangeable); hasattr(type(x), 'm') might find a *metaclass* method.
Example of the former (assume Python 3):
class C: def __add__(self, other): return 42
c = C() c.__add__ = lambda *args: 0 c + 1 # prints 42, not 0
Example of the latter:
class C: pass c = C() hasattr(C, 'mro') # prints True, since mro() is a method of the standard metaclass ('type'). c.mro() # raises AttributeError
The use case I am mainly thinking of is the formal explanation of the semantics of binary (and other) operators, e.g.
def __add__(a, b): r = NotImplemented if hasmethod(a, '__add__'): r = a.__add__(b) if r is NotImplemented and hasmethod(b, '__radd__'): r = b.__radd__(a) if r is NotImplemented: raise TypeError return r
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)) Cheers, Sven