Python 3默认情况下是什么“ __new __”?

时间:2019-08-08 22:18:00

标签: python python-3.x default-constructor class-constructors

我相信我对__new__应该做的事情有某种理解(创建类的实例,但不初始化它,这是__init__的工作)。不过,我想了解Python 3默认情况下是作为__new__方法实现的。

我还发现cls__new__的参数有点令人困惑,但是__new__是静态方法而不是类方法(我从documentation获得了此方法) ...现在如何将类型作为其第一个参数传递给它?

2 个答案:

答案 0 :(得分:2)

第一部分:__new__的默认设置是什么?因为从头开始创建对象是一项基本的,特定于实现的操作,所以object.__new__的定义必定是实现本身的一部分(就像object的其余部分一样)。这意味着您需要查看CPython,PyPy,Cython等的源代码,以确切了解如何在任何特定的Python实现中管理对象创建。通常,所有这些低级别的簿记都是无法直接从Python本身直接访问的。

第二部分:__new__如何知道它得到一个类参数?因为它假定的第一个参数是一个类,并且调用者最好期望__new__正常工作,所以最好提供一个类!就是说,除了通过__new__的覆盖中的super之外,没有人真正真正地__new__调用过,然后,您必须确保自己明确地传递cls:< / p>

def __new__(cls, *args, **kwargs):
    rv = super().__new__(cls, *args, **kwargs)  # Not super().__new__(*args, **kwargs)

其余时间,您不是通过直接调用Foo而是仅通过调用类型本身Foo.__new__(Foo, ...)来创建类Foo(...)的实例。 对此进行管理是因为__call__的元类的Foo方法可以为您调用__new__。例如,您可以想象type.__call__被大致定义为

# A regular instance method of type; we use cls instead of self to
# emphasize that an instance of a metaclass is a class
def __call__(cls, *args, **kwargs):
    rv = cls.__new__(cls, *args, **kwargs)  # Because __new__ is static!
    if isinstance(rv, cls):
        rv.__init__(*args, **kwargs)
    return rv

请注意,只有在__init__实际上首先返回调用__new__的类的实例时,才会调用__new__

答案 1 :(得分:0)

根据我的理解,__new__()的默认实现是这样的

class Default(object):
def __new__(cls, *args, **kwargs):
    print("In new")
    return super().__new__(cls,*args, **kwargs)

def __init__(self):
    print("In init default")

default = Default()
print(type(default))

输出

In new
In init default
<class '__main__.Default'>

基于文档 https://docs.python.org/3/reference/datamodel.html#object.new

  

典型的实现通过使用super()调用超类的__new__()方法来创建该类的新实例。 new (cls [,...])和适当的参数,然后进行修改返回之前,根据需要创建新实例。

super().__new__()调用将创建实例,__init__()将初始化。

下面的代码显示__new__()的错误覆盖

class InccorectOverride(object):

def __new__(cls, *args, **kwargs):
    pass

def __init__(self):
    print("In init InccorectOverride")

a = InccorectOverride()
print(type(a))

输出

<class 'NoneType'>

由于__new__()不返回实例,因此输出的值为NoneType

希望这能回答您的问题