【问题标题】:decorate __call__ with @staticmethod用@staticmethod 装饰__call__
【发布时间】:2015-01-03 19:02:48
【问题描述】:

为什么我不能使用 @staticmethod 装饰器将类的 __call__ 方法设为静态?

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

    @staticmethod
    def __call__():
        return '__call__'

print Foo.bar()
print Foo()

输出

bar
<__main__.Foo object at 0x7fabf93c89d0>

但我希望它能够输出

bar
__call__

【问题讨论】:

    标签: python decorator static-methods python-decorators


    【解决方案1】:

    您需要覆盖元类上的__call__。类中定义的特殊方法是针对其实例的,要更改类的特殊方法,您需要在其类中更改它们,即元类。 (当你调用Foo()时,通常顺序是:Meta.__call__() --> Foo.__new__() --> Foo.__init__(),只要它们正常返回)

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

    当您尝试修改类实例化时,另一种方法是覆盖类本身的__new__ 并从中返回__call__(当__new__ 返回的不是实例时,__init__ 方法是从未调用过):

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

    【讨论】:

    • 谢谢!这对我来说很清楚。 Meta.__call__() --> Foo.__new__() --> Foo.__init__() 是什么意思?箭头表示“呼叫”吗?
    • @fragapanagos 这是实例化类时 Python 遵循的顺序。见:ideone.com/4gxeiN
    • 可以通过从type继承所需的类型来跳过元对象吗?
    猜你喜欢
    • 1970-01-01
    • 2013-10-30
    • 2023-03-23
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2020-05-23
    • 2015-03-24
    • 2021-09-29
    相关资源
    最近更新 更多