python __new__ - 必须返回cls的实例

时间:2016-07-29 19:07:40

标签: python super python-internals

According to the docs,

  

典型实现通过调用创建类的新实例   超类的__new__()方法使用super(currentclass, cls).__new__(cls[, ...])和适当的参数然后修改   在返回之前,必要时新创建的实例。
  ...

     

如果__new__没有返回cls的实例,那么新的   

。实例的__init__()方法不会被调用。

simplest implementation of __new__:

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

2 个答案:

答案 0 :(得分:1)

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

在您的情况下,即object.__new__

>>> 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() function;它包含一个抽象基类的钩子,以确保您没有尝试实例化一个抽象类,然后委托tp_alloc槽,通常将设置为PyType_GenericAlloc,这将添加一个新的{{ 1}} struct到堆。它是表示解释器实例的结构。

答案 1 :(得分:0)

首先,你需要从object编写显式继承,如下所示:

class MyClass(object):

你应该在python上阅读old classes and new classes(仅在python 2上,在python 3中没关系)

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

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

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

修改 阅读完你的评论之后,我只想补充一点,super()不必在Python 3中使用任何参数,所以对你来说这可能更为微不足道。强烈建议您详细了解super() here