Python 3 中默认的"__new__"是什么?



我相信我对__new__应该做什么有某种理解(创建一个类的实例,但不初始化它,这是__init__的工作(。但是,我想了解Python 3默认作为__new__方法实现的内容。

我也发现有点令人困惑的是,cls__new__的参数,但__new__是一个静态方法而不是类方法(我从文档中得到了这个(。它如何知道它正在传递一个类型作为其第一个参数?

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

第二部分:__new__怎么知道它得到了一个类参数?因为它假设它的第一个参数是一个类,如果调用者希望__new__正常工作,他们最好提供一个类!也就是说,没有人真正明确地调用__new__,除非通过super覆盖__new__,然后,您必须确保自己明确传递cls

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

其余时间,您不是通过直接调用Foo.__new__(Foo, ...)而是通过调用类型本身来创建类Foo实例:Foo(...)这是管理的,因为Foo元类的__call__方法负责为你调用__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

请注意,仅当__new__首先实际返回调用__new__类的实例时,才会调用__init__

根据我的理解,__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。新增功能

典型的实现通过使用 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

希望这能回答你的问题

你的问题是

如果我们不覆盖它,那么__new__在 Python 中做什么?


假设我们有一个名为Point的非常简单的类。我们按如下方式实例化Point类:

# construct and initialize paula the point
paula = Point(10.2, 7.4)

为了帮助解释__new__的作用,我将编写一个名为make_point的类方法,它的行为与调用类构造函数的行为几乎相同,例如paula = = Point(10.2, 7.4)

class Point():
def __new__(cls, *args, **kwargs):
print("__new__(" + ", ".join(str(x) for x in [cls, *args]) + ")")
obj = super().__new__(cls)
return obj
def __init__(self, y:float, y:float):
args = (y, y)
print("__init__(" + ", ".join(str(x) for x in [self, *args]) + ")")
self._y = y
self._y = y
@classmethod
def make_point(cls, *args):
new_instance = cls.__new__(cls, *args)
if isinstance(new_instance, cls):
cls.__init__(new_instance, *args)
return new_instance

现在我们可以实例化Point类,如下所示:

peter = Point.make_point(59.87, 5.91)

最新更新