在尝试理解元类创建类实例的顺序时,我感到困惑.根据该图(source),
我键入以下代码进行验证.
class Meta(type):
def __call__(self):
print("Meta __call__")
super(Meta, self).__call__()
def __new__(mcs, name, bases, attrs, **kwargs):
print("Meta __new__")
return super().__new__(mcs, name, bases, kwargs)
def __prepare__(msc, name, **kwargs):
print("Meta __prepare__")
return {}
class SubMeta(Meta):
def __call__(self):
print("SubMeta __call__!")
super().__call__()
def __new__(mcs, name, bases, attrs, **kwargs):
print("SubMeta __new__")
return super().__new__(mcs, name, bases, kwargs)
def __prepare__(msc, name, **kwargs):
print("SubMeta __prepare__")
return Meta.__prepare__(name, kwargs)
class B(metaclass = SubMeta):
pass
b = B()
但是,结果似乎不是这样的.
SubMeta __prepare__
Meta __prepare__
SubMeta __new__
Meta __new__
SubMeta __call__!
Meta __call__
任何帮助将不胜感激. 解决方法: 尽管@ torek的长篇答案,以及关于课堂创作的许多其他细节,你在这个问题上汇集的内容大多是正确的.
你的代码中唯一错误的就是让你感到困惑的是你调用Meta的te类本身就是SubMeta的元类,而不是它的父元素.
只需将Submeta声明更改为:
class SubMeta(type, metaclass=Meta):
...
(也不需要它继承“Meta” – 它只能从类型派生.除此之外,我想要定制类型.__ call__,这对于创建类的实例同时是有用的(当调用SubMeta .__ call__时,你的类本身(调用Meta .__ call__))
这是我刚在终端输入的另一个较短的例子.很抱歉命名不一致,并且不太完整 – 但它显示了要点:
class M(type):
def __call__(mmcls, *args, **kwargs):
print("M's call", args, kwargs)
return super().__call__(*args, **kwargs)
class MM(type, metaclass=M):
def __prepare__(cls, *args, **kw):
print("MM Prepare")
return {}
def __new__(mcls, *args, **kw):
print("MM __new__")
return super().__new__(mcls, *args, **kw)
class klass(metaclass=MM):
pass
在处理klass体时,Python输出是:
MM Prepare
M's call ('klass', (), {'__module__': '__main__', '__qualname__': 'klass'}) {}
MM __new__
此外
正如您所看到的,使用元元类,可以自定义元类__init__和__new__的调用顺序和参数,但仍然存在无法从纯Python代码自定义的步骤,并且需要对API的本机调用(以及可能的原始对象结构操作) – 即:
>无法控制对__prepare__的调用 >无法控制对创建的类的__init_subclass__的调用 >可以控制何时调用描述符’__set_name__
最后两个项目发生在meta-meta的__call__返回之后,并且在将流程恢复到类模块所在的模块之前. 来源:http://www./content-1-228701.html
|