为什么metaclass的__call__方法在类上调用,但是本机类的__call__不是?

时间:2015-06-16 06:52:56

标签: python oop metaclass

class Meta(type):
    def __call__(cls, *args, **kwargs):
        print 'Meta.__call__ called.'
        return super(Meta, cls).__call__(*args, **kwargs)


class MetaInstance(object):
    __metaclass__ = Meta

# Instantiate class.
MetaInstance()  # Meta.__call__ called.


class StandardClass(object):
    @classmethod
    def __call__(cls, *args, **kwargs):
        print 'StandardClass.__call__ called.'
        return super(StandardClass, cls).__call__(*args, **kwargs)

# Instantiate class.
StandardClass()  # StandardClass.__call__ is not called!

为什么metaclass的__call__方法在类上调用,而本机类的__call__不在我实例化类时?

2 个答案:

答案 0 :(得分:3)

创建类实例时,将调用元类(其类为实例)__call__

# Instantiate class.
StandardClass()  # StandardClass.__call__ is not called!

当您创建一个类实例然后“调用”该实例时,将调用该类的__call__。我不认为用__call__装饰classmethod会起作用。

这会调用你的元类和类的__call__ s:

StandardClass()()

答案 1 :(得分:2)

因为magic methods are looked up on the class。换句话说,当您在类上编写__call__方法时,它会定义在调用该类的实例时会发生什么,而不是在调用类本身时会发生什么。类是其元类的实例,因此在元类上定义__call__定义了在调用类时会发生什么。

你可以在你的例子中看到你在两种情况下没有做同样的事情。对于元类示例,您定义了两个东西,一个元类和一个“元实例”(即一个常规类),并且您调用了第二个。对于第二个示例,您只定义了一个事物(一个类)。要与第一个示例并行,您需要创建一个StandardClass的实例,然后调用它,在这种情况下将调用StandardClass.__call__