使用元类理解 __call__ [重复]
Posted
技术标签:
【中文标题】使用元类理解 __call__ [重复]【英文标题】:Understanding __call__ with metaclasses [duplicate] 【发布时间】: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__
方法被调用的。这是如何工作的?
【问题讨论】:
【参考方案1】:元类实现类的行为方式(而不是实例)。因此,当您查看实例创建时:
x = Foo()
这实际上是“调用”类Foo
。这就是为什么在您的类的 __new__
和 __init__
方法初始化实例之前调用元类的 __call__
。
正如@Take_Care_ 在 cmets 中指出的那样,关于元类的一个重要资源是 ionelmc's blog post 关于“理解 Python 元类”。该博文中的一张图片直接适用于您的情况:
图片是直接从博文中复制过来的。
【讨论】:
伟大而简单的答案! .如果 OP 想要更多:blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses 谢谢。这正是我想要的!【参考方案2】:一个类只是它的元类的一个实例。由于元类定义了__call__()
,调用元类的实例,即类,作为一个函数,即作为一个构造函数,将调用它。
【讨论】:
以上是关于使用元类理解 __call__ [重复]的主要内容,如果未能解决你的问题,请参考以下文章
为啥元类的 __call__ 方法在类上调用,而原生类的 __call__ 没有?
自定义元类 __call__,__init__,__new__总结