python 3.7中对象与类型的super().__ new __()。

发布时间:2020-07-06 21:28

在元类中重写super().__new__()时调用__new__包含以下函数签名:

class MyMeta(type):
    
    def __new__(cls, name, bases, classdict):
        clsobj = super().__new__(cls, name, bases, classdict)

但是,当在常规类中覆盖__new__时,我们具有以下内容:

class A:

    def __new__(cls, *a, **kw):
        clsobj = super().__new__(cls)

将任何其他参数传递给super()中的A.__new__会导致以下错误:

TypeError: object.__new__() takes exactly one argument (the type to instantiate)

我了解在第二种情况下,我们正在处理object.__new__,而在第一种情况下,我们正在处理type.__new__

我的问题是,为什么这些功能签名不同?为什么object.__new__只接受cls

回答1

objecttype有一个有趣的关系。 objecttype的实例,但是typeobject的子类。

然而,

__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)

您会看到B("B", (), {})输出In B.__new__而不是In A.__new__。可以这么说,type.__new__是行的结尾。

但是,通常,您不会混合这样的类。就像您很少在类的基类列表中包含object(我几乎愿意说您永远一样)一样,您通常不会从{{1} }和另一个(元)类,我想不出任何理由尝试同时继承typetype的非类型子类。