[Python-ideas] Add a "hasmethod()" builtin?

Sven Marnach sven at marnach.net
Thu Aug 30 01:13:21 CEST 2012


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



More information about the Python-ideas mailing list