Python 3.7 中对象与类型的 super().__new__()

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

che*_*ner 5

objecttype有着有趣的关系。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