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

问题描述 投票:0回答:3

我相信我对

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

我还发现

cls
__new__
的参数有点令人困惑,但是
__new__
是静态方法而不是类方法(我从 documentation 中得到这个)。它怎么知道它被传递一个类型作为它的第一个参数?

python python-3.x default-constructor class-constructors
3个回答
16
投票

第一部分:

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

第二部分:

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

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__


2
投票

根据我的理解,

__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
(cls[, ...]) 和适当的参数调用超类的__new__() 方法来创建类的新实例,然后在返回之前根据需要修改新创建的实例它。

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

希望这能回答你的问题


0
投票

你的问题是

如果我们不覆盖它,那么

__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)
© www.soinside.com 2019 - 2024. All rights reserved.