【发布时间】:2019-12-30 19:40:14
【问题描述】:
我的问题受到了question 的启发。
问题在于 3 级类模型 - 终止类(第 3 级)只应存储在注册表中,但第 2 级干扰并且也已存储,因为它们是 1- 的子类st级。
我想通过使用元类来摆脱一级类。通过这种方式,剩下的只有 2 个类级别 - 每组设置及其子级的基类 - 从相应的基类继承的各种设置类。元类充当类工厂 - 它应该创建具有所需方法的基类,并且不应该显示在继承树中。
但我的想法不起作用,因为似乎__init_subclass__ 方法(方法的链接)没有从元类复制到构造类。与__init__ 方法相比,它按我的预期工作。
代码sn-p№1.模型的基本框架:
class Meta_Parent(type):
pass
class Parent_One(metaclass=Meta_Parent):
pass
class Child_A(Parent_One):
pass
class Child_B(Parent_One):
pass
class Child_C(Parent_One):
pass
print(Parent_One.__subclasses__())
输出:
[<class '__main__.Child_A'>, <class '__main__.Child_B'>, <class '__main__.Child_C'>]
我想为上述模型的子类化过程添加功能,所以我重新定义了type的内置__init_subclass__,如下所示:
代码 sn-p № 2。
class Meta_Parent(type):
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
print(cls)
在我看来,现在每个由 Meta_Parent 元类(例如 Parent_One)构建的新类都应该有 __init_subclass__ 方法,因此应该打印当每个类都继承自这个新类时的子类名称,但它什么也不打印。也就是说,发生继承时不会调用我的__init_subclass__ 方法。
如果 Meta_Parent 元类是直接继承的,它会起作用:
代码 sn-p № 3。
class Meta_Parent(type):
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
print(cls)
class Child_A(Meta_Parent):
pass
class Child_B(Meta_Parent):
pass
class Child_C(Meta_Parent):
pass
输出:
<class '__main__.Child_A'>
<class '__main__.Child_B'>
<class '__main__.Child_C'>
这里没什么奇怪的,__init_subclass__ 正是为此目的而创建的。
我当时在想,dunder 方法仅属于元类,不会传递给新构造的类,但是后来,我尝试了 __init__ 方法,它就像我一开始所期望的那样工作 - 看起来像__init__ 的链接已复制到每个元类的类。
代码 sn-p № 4。
class Meta_Parent(type):
def __init__(cls, name, base, dct):
super().__init__(name, base, dct)
print(cls)
输出:
<class '__main__.Parent_One'>
<class '__main__.Child_A'>
<class '__main__.Child_B'>
<class '__main__.Child_C'>
问题:
- 为什么
__init__有效,而__init_subclass__无效? - 是否可以通过使用元类来实现我的想法?
【问题讨论】:
标签: python-3.x metaclass