我相信我对应该做什么有一定的了解__new__
(创建一个类的实例,但不初始化它,这是 的工作__init__
)。但是,我想了解 Python 3__new__
默认作为方法实现的内容。
我也觉得它cls
的一个参数有点令人困惑__new__
,但__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
其余时间,您不是通过Foo.__new__(Foo, ...)
直接调用,而是通过调用类型本身来创建类的实例: Foo(...)
. 这是管理的,因为 's 元类的__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__
首先调用的类的实例时才会调用。
根据我的理解,默认实现__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
希望这能回答你的问题