gpt4 book ai didi

Python 元类行为(不调用 __new__),有解释吗?

转载 作者:行者123 更新时间:2023-12-01 12:37:22 26 4
gpt4 key购买 nike

在名为 exp.py(如下)的文件中,我试图理解 Python 中的元类。看起来当元类的 __new__ 方法使用“类型”构造函数构造一个类时,它的 __new__ 方法不会被使用它作为类的子类调用元类:

class A(type):
def __new__(cls, name, bases, dct):
print "cls is: ", cls
print "name is: ", name
print "bases is: ", bases
print "dct is: ", dct
print
return super(A, cls).__new__(cls, name, bases, dct)

class B(object):
__metaclass__ = A

class C(B): pass

class D(type):
def __new__(cls, name, bases, dct):
print "cls is: ", cls
print "name is: ", name
print "bases is: ", bases
print "dct is: ", dct
return type(name, bases, dct)

class E(object):
__metaclass__ = D

class F(E): pass

在终端中:

>>> from exp import *
cls is: <class 'exp.A'>
name is: B
bases is: (<type 'object'>,)
dct is: {'count': 0, '__module__': 'exp', '__metaclass__': <class 'exp.A'>, '__init__': <function __init__ at 0x107eb9578>}

cls is: <class 'exp.A'>
name is: C
bases is: (<class 'exp.B'>,)
dct is: {'__module__': 'exp'}

cls is: <class 'exp.D'>
name is: E
bases is: (<type 'object'>,)
dct is: {'count': 0, '__module__': 'exp', '__metaclass__': <class 'exp.D'>, '__init__': <function __init__ at 0x107ebdb18>}
>>>

如您所见,加载类 F 的定义时,不会调用元类 D 的 __new__ 方法。 (如果它被调用,那么关于类 F 的信息也会被打印出来。)

谁能帮我解释一下?


相关帖子:我正在阅读 What is a metaclass in Python? , 似乎遇到类似的句子,“这里要小心__metaclass__属性不会被继承,父类(Bar.__class__)的元类将是. 如果 Bar 使用 __metaclass__ 属性创建 Bar with type()(而不是 type.__new__()),子类将不会继承那种行为。”但是我没有完全理解这一点。

最佳答案

在第二种情况下,您实际上返回的不是元类的实例,而是 type 的实例。 , 这又设置了 __class__新创建类的属性 E作为<type 'type'>而不是 D .因此 as per the rule 2 Python 检查基类的 __class__属性(或 type(E)E.__class__ )并决定使用 type作为F的元类,所以 D__new__在这种情况下永远不会被调用。

  • 如果dict['__metaclass__']存在,它被使用。
  • 否则,如果至少有一个基类,则使用其元类(这首先查找 __class__ 属性,如果未找到,则使用其类型)。

因此,正确的方法是调用类型的 __new__元类中的方法 __new__方法:

class D(type):
def __new__(cls, name, bases, dct):
print "cls is: ", cls
print "name is: ", name
print "bases is: ", bases
print "dct is: ", dct
return type.__new__(cls, name, bases, dct)

class E(object):
__metaclass__ = D

class F(E): pass

class A(object):
pass

输出:

cls is:    <class '__main__.D'>
name is: E
bases is: (<type 'object'>,)
dct is: {'__module__': '__main__', '__metaclass__': <class '__main__.D'>}
cls is: <class '__main__.D'>
name is: F
bases is: (<class '__main__.E'>,)
dct is: {'__module__': '__main__'}

关于Python 元类行为(不调用 __new__),有解释吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28465955/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com