【问题标题】:Why the metaclass' s __new__ is called为什么调用元类的 __new__
【发布时间】:2019-09-26 01:35:42
【问题描述】:

使用 Python 元类 A 创建一个新类 B

C继承自B时,为什么会调用A__new__方法?

class A(type):
    def __new__(cls, name, bases, attrs):
        print(" call A.__new__  ")
        return type.__new__(cls, name, bases, attrs)


B = A("B", (), {})


class C(B):
    pass                  
python test.py 
call A.__new__  
call A.__new__  

【问题讨论】:

  • C 是 A 的一个实例,就像 B 是 A 的一个实例一样。
  • 你为什么期望A.__new__ 不会被调用? B 是从A 创建的,而不是标准的type,并且C 继承B
  • @jonrsharpe 我感到困惑的是 C 不是 A 的子类。
  • 不,但它是 metaclassA 的东西的子类。

标签: python metaclass


【解决方案1】:

类是元类的实例,默认的元类type派生自object。因此,元类遵循创建object 实例的常规规则 - __new__ 构造实例,__init__ 可以初始化它。

>>> class DemoClass(object):
...     def __new__(cls):
...         print('__new__ object of DemoClass')
...         return super().__new__(cls)
...
...     def __init__(self):
...         print('__init__ object of DemoClass')
...         return super().__init__()
...
>>> demo_instance = DemoClass()  # instantiate DemoClass
__new__ object of DemoClass
__init__ object of DemoClass

当我们的类是元类时也会发生同样的情况 - 它仍然是 object 并且行为如此。

>>> class DemoType(type):
...     def __new__(mcs, name, bases, attrs):
...         print('__new__ object %r of DemoType' % name)
...         return super().__new__(mcs, name, bases, attrs)
...
...     def __init__(self, name, bases, attrs):
...         print('__init__ object %r of DemoType' % name)
...         return super().__init__(name, bases, attrs)
...
>>> demo_class = DemoType('demo_class', (), {})  # instantiate DemoType
__new__ object 'demo_class' of DemoType
__init__ object 'demo_class' of DemoType

重申,如果aA 的一个实例,那么A.__new__ 用于创建a。这同样适用于类和元类,因为前者是后者的实例。

类不会从其元类继承__new__。一个类一个元类,元类的__new__ 用于创建类。


当从一个类(元类的实例)继承时,元类也被继承。这意味着子类也是元类的一个实例。因此,元类的__new____init__ 都用于构造和初始化这个实例。

>>> class DemoClass(metaclass=DemoType):
...     ...
...
>>> class DemoSubClass(DemoClass):
...     ...
...
__new__ object 'DemoClass' of DemoType
__init__ object 'DemoClass' of DemoType
__new__ object 'DemoSubClass' of DemoType
__init__ object 'DemoSubClass' of DemoType
>>> type(DemoClass)  # classes are instances of their metaclass
__main__.DemoType
>>> type(DemoSubClass)  # subclasses inherit metaclasses from base classes
__main__.DemoType

这样做的目的是元类存在于define how classes are created。这包括子类。为每个子类调用 __new__ 可以让元类对新的类主体、额外的基类和命名空间以及关键字做出反应。

【讨论】:

  • type 实际上是 type 类型。
  • 两者兼有。 objecttype 都是 objecttype 的实例。 isinstance(type, object) == isinstance(type, type) == isinstance(object, type)。但是你是正确的 type 的类是 type 本身。
  • 是的,我的意思是type(type)
  • @gmds 你说得对,这令人困惑。我已经稍微改变了措辞,希望不要误导。
  • @MisterMiyagi 好答案
猜你喜欢
  • 2021-06-03
  • 1970-01-01
  • 2010-10-15
  • 2015-04-12
  • 2012-02-23
  • 1970-01-01
相关资源
最近更新 更多