【问题标题】:Understanding __call__ with metaclasses [duplicate]使用元类理解 __call__ [重复]
【发布时间】:2018-01-14 03:37:22
【问题描述】:

据我了解,类内部的__call__方法实现了函数调用操作符,例如:

class Foo:
    def __init__(self):
        print("I'm inside the __init__ method")

    def __call__(self):
        print("I'm inside the __call__ method")

x = Foo() #outputs "I'm inside the __init__ method"
x() #outputs "I'm inside the __call__ method"

但是,我正在浏览Python Cookbook,作者定义了一个元类来控制实例创建,因此您无法直接实例化对象。他是这样做的:

class NoInstance(type):
    def __call__(self, *args, **kwargs):
        raise TypeError("Can't instantaite class directly")


class Spam(metaclass=NoInstance):
    @staticmethod
    def grok(x):
        print("Spam.grok")

Spam.grok(42) #outputs "Spam.grok"

s = Spam() #outputs TypeError: Can't instantaite class directly

但是,我不明白s() 是如何被调用的,但它是__call__ 方法被调用的。这是如何工作的?

【问题讨论】:

    标签: python class metaprogramming metaclass


    【解决方案1】:

    元类实现类的行为方式(而不是实例)。因此,当您查看实例创建时:

    x = Foo()
    

    这实际上是“调用”类Foo。这就是为什么在您的类的 __new____init__ 方法初始化实例之前调用元类的 __call__


    正如@Take_Care_ 在 cmets 中指出的那样,关于元类的一个重要资源是 ionelmc's blog post 关于“理解 Python 元类”。该博文中的一张图片直接适用于您的情况:

    图片是直接从博文中复制过来的。

    【讨论】:

    【解决方案2】:

    一个类只是它的元类的一个实例。由于元类定义了__call__(),调用元类的实例,即类,作为一个函数,即作为一个构造函数,将调用它。

    【讨论】:

      猜你喜欢
      • 2020-04-20
      • 2014-08-11
      • 2011-10-21
      • 2015-08-31
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      • 2017-11-06
      • 1970-01-01
      相关资源
      最近更新 更多