【问题标题】:super().__new__() for object vs type in Python 3.7super().__new__() 用于 Python 3.7 中的对象与类型
【发布时间】:2020-10-27 02:13:01
【问题描述】:

在元类中覆盖 __new__ 时调用 super().__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)

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

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

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

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

【问题讨论】:

  • 是的,函数签名不同。因为type.__new__object.__new__ 做不同的事情。虽然,也许真正的问题是,为什么 object.__new__ 不接受 any 参数,例如*args, **kwargs...

标签: python python-3.7 super metaclass


【解决方案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 包含在类的基类列表中(我几乎愿意说您从不),您通常不会从 type 和另一个 ( meta)class,我想不出你为什么要尝试从typeobject 的非类型子类继承。

【讨论】:

  • Python 文档中是否表达了这种区别?我一直试图在文档中发现它,但一直没能。
  • 据我所知,不明确。但这是第一句中概述的关系的逻辑结果(您可以使用instanceof(object, type)issubclass(type, object) 进行验证)。
猜你喜欢
  • 1970-01-01
  • 2012-09-21
  • 1970-01-01
  • 2012-11-11
  • 1970-01-01
  • 2020-04-22
  • 1970-01-01
  • 2011-11-25
  • 1970-01-01
相关资源
最近更新 更多