Search code examples
pythondecoratorstatic-methodspython-decorators

decorate __call__ with @staticmethod


Why can't I make a class' __call__ method static using the @staticmethod decorator?

class Foo(object):
    @staticmethod
    def bar():
        return 'bar'

    @staticmethod
    def __call__():
        return '__call__'

print Foo.bar()
print Foo()

outputs

bar
<__main__.Foo object at 0x7fabf93c89d0>

but I would expect it to output

bar
__call__

Solution

  • You need to override __call__ on the metaclass. The special methods defined in a class are for its instances, to change a class's special methods you need to change them in its class, i.e metaclass. (When you call Foo() usually the order is: Meta.__call__() --> Foo.__new__() --> Foo.__init__(), only if they return normally)

    class Meta(type):
        @staticmethod 
        def __call__():
            return '__call__'
    
    
    class Foo(object):
        __metaclass__ = Meta
    
        @staticmethod
        def bar():
            return 'bar'
    
    print Foo()
    #__call__
    

    As you're trying to modify class instantiation, another way will be to override __new__ on the class itself and return __call__ from it(when __new__ returns something other than an instance the __init__ method is never called):

    class Foo(object):
    
        def __new__(*args):
            #ignore the args 
            return '__call__'
    
        @staticmethod
        def bar():
            return 'bar'
    
    print Foo()
    #__call__