Alg*_*ra8 1 python metaclass super python-3.7
super().__new__()在元类中重写时调用__new__包含以下函数签名:
class MyMeta(type):
def __new__(cls, name, bases, classdict):
clsobj = super().__new__(cls, name, bases, classdict)
Run Code Online (Sandbox Code Playgroud)
然而,当__new__在普通类中重写时,我们有以下内容:
class A:
def __new__(cls, *a, **kw):
clsobj = super().__new__(cls)
Run Code Online (Sandbox Code Playgroud)
将任何其他参数传递给super()inA.__new__将导致以下错误:
TypeError: object.__new__() takes exactly one argument (the type to instantiate)
Run Code Online (Sandbox Code Playgroud)
据我所知,在第二种情况下,我们正在处理object.__new__,而在第一种情况下,我们正在处理type.__new__。
我的问题是,为什么这些函数签名不同?为什么object.__new__只接受cls?
object并type有着有趣的关系。object是 的实例type,但是type是 的子类object。
__new__然而,它侧重于创建类的实例,因此object.__new__最低公分母也是如此:它本身几乎不执行任何操作,因为每个可能的类的实例实际上没有任何共同点。因此,object.__new__除了返回值的类型之外,不需要更多的信息。
type.__new__所做的不仅仅是object.__new__:它必须创建一个本身能够创建新对象的对象。这需要更多的信息,因此type.__new__在覆盖时定义几个附加参数object.__new__。
但请注意,它type本身不使用super; 如果你定义了两个类
class A:
def __new__(cls, *args, **kwargs):
print("In A.__new__")
return super().__new__(cls)
class B(type, A):
def __new__(cls, name, bases, dct, *args, **kwargs):
print("In B.__new__")
return super().__new__(cls, name, bases, dct)
Run Code Online (Sandbox Code Playgroud)
你会看到B("B", (), {})输出In B.__new__,但不是In A.__new__。type.__new__可以说,这是创建元类的最后一步。
不过,通常情况下,您不会像这样混合使用类。就像你很少包含object在一个类的基类列表中一样(我几乎愿意说你永远不会),你不经常继承type另一个(元)类,我想不出任何原因为什么你会尝试从 .type和 . 的非类型子类继承object。