关于super:python __new__ – 必须返回cls的实例

python __new__ - must return an instance of cls

据文件记载,

Typical implementations create a new instance of the class by invoking
the superclass’s __new__() method using super(currentclass,
cls).__new__(cls[, ...])
with appropriate arguments and then modifying
the newly-created instance as necessary before returning it.
...

If __new__ does not return an instance of cls, then the new
instance’s __init__() method will not be invoked.

__new__的最简单实现:

1
2
3
4
class MyClass:
    def __new__(cls):
        RetVal = super(currentclass, cls).__new__(cls)
        return RetVal

super(currentclass, cls).__new__(cls[, ...])如何返回cls类型的对象?

该声明称为object.__new__(cls),其中clsMyClass

那么,类object如何知道如何创建类型MyClass


super(MyClass, cls).__new__(cls)首先搜索cls对象的mro(方法解析顺序)(在该序列中跳过MyClass),直到找到具有__new__属性的对象。

在您的情况下,这是object.__new__

1
2
3
4
5
6
7
8
9
>>> class MyClass:
...     def __new__(cls):
...         RetVal = super(MyClass, cls).__new__(cls)
...         return RetVal
...
>>> MyClass.__mro__
(<class '__main__.MyClass'>, <class 'object'>)
>>> hasattr(MyClass.__mro__[1], '__new__')
True

但是,如果您将MyClass子类化,并使用__new__方法将另一个类混合到MRO中,那么它可能是另一个方法。

object.__new__在c中实现,参见object_new()函数;它包含一个抽象基类挂钩,以确保您不尝试实例化一个抽象类,然后委托给tp_alloc槽,该槽通常设置为PyType_GenericAlloc,这会向堆添加一个新的PyObject结构。它是表示解释器实例的结构。


很少有事情,首先您需要这样写来自object的明确继承:

1
class MyClass(object):

您应该阅读关于python的旧类和新类(仅在python 2上,在python 3中不重要)

对于您的问题,我认为您错过了super()函数的要点或语法。同样,代码的小改动:

1
RetVal = super(MyClass, cls).__new__(cls)

通过这种方式,您可以使用super(MyClass, cls)引用父类,并从这个父类调用一个新方法(当然,您可以使用任何其他方法)。

编辑在阅读了您的评论之后,我将补充一点,super()不需要在python 3中使用任何参数,所以它对您来说可能更为琐碎。强烈建议在这里阅读更多关于super()的信息。