Search code examples
pythonclassmethodsdecoratorpython-decorators

Decorators and class method


I am having trouble understanding why the following happens. I am having a decorator which does nothing except it checks whether a function is a method. I thought I have understood what method in Python is, but obviously, this is not the case:

import inspect

def deco(f):
    def g(*args):
        print inspect.ismethod(f)
        return f(*args)
    return g

class Adder:
    @deco
    def __call__(self, a):
        return a + 1

class Adder2:
    def __call__(self, a):
        return a + 2
Adder2.__call__ = deco(Adder2.__call__)

Now, running the following:

>>> a = Adder()
>>> a(1)
False
2
>>> a2 = Adder2()
>>> a2(1)    
True
3

I would expect for this code to print True two times.

So, decorating the function manually as in the Adder2 is not an exact equivalent to decorating via the @deco function?

Can someone be so glad and explain why this happens?


Solution

  • Inside a class definition, __call__ is a function, not a method. The act of accessing the function through attribute lookup (e.g. using the dot syntax), such as with Adder2.__call__, returns an unbound method. And a2.__call__ returns a bound method (with self bound to a2).

    Note that in Python3 the concept of unbound method has been dropped. There, Adder2.__call__ is a function as well.