pythonclassmethodscall

__call__ method as classmethod not working?


I was wondering why the call method inside of my class was not functioning when i declared the function as a classmethod. Here is an example:

class Foo:
    bar = 0
    @classmethod
    def __call__(cls):
        print(cls.bar)

When i use Foo() it does not print out bar. Why?


Solution

  • @classmethod doesn't change when method lookup will find a method. It only changes what arguments get bound when a method is found.

    Putting @classmethod on your __call__ means that if you call an instance of your Foo class:

    foo = Foo()  # not here
    foo()        # here
    

    the first argument to __call__ will be the class, not the instance.

    Putting @classmethod on your __call__ will not mean that the method gets used for calling Foo itself. When looking up magic methods to implement language features, Python will in almost all cases bypass the ordinary method lookup procedure and perform a direct search through the object's class's MRO. Among other reasons, this avoids using Foo.__call__ for Foo() in the much more common case where Foo.__call__ is an instance method and was never intended to be called to implement the Foo() operation itself.

    For a call Foo(), the object is Foo itself and its class is type, so the __call__ lookup finds type.__call__, bypassing anything defined directly on Foo.