Nei*_*l G 29 python initialization
在Python中,__new__用于初始化不可变类型,__init__通常初始化可变类型.如果__init__从语言中删除,那么就不能再轻松完成了什么?
例如,
class A:
def __init__(self, *, x, **kwargs):
super().__init__(**kwargs)
self.x = x
class B(A):
def __init__(self, y=2, **kwargs):
super().__init__(**kwargs)
self.y = y
Run Code Online (Sandbox Code Playgroud)
可以__new__像这样重写:
class A_N:
def __new__(cls, *, x, **kwargs):
obj = super().__new__(cls, **kwargs)
obj.x = x
return obj
class B_N(A_N):
def __new__(cls, y=2, **kwargs):
obj = super().__new__(cls, **kwargs)
obj.y = y
return obj
Run Code Online (Sandbox Code Playgroud)
澄清问题范围:这不是关于如何使用__init__和__new__使用它们或它们之间有什么区别的问题.这是一个关于如果__init__从语言中删除会发生什么的问题.什么事情会破裂?有什么事情会变得更难或不可能吗?
And*_*yko 19
在解释缺失的功能之前,让我们回到定义__new__和__init__:
__new__是实例创建的第一步.它首先被调用,并负责返回您的类的新实例.
但是,__ init__不会返回任何内容 ; 它只负责在创建实例后初始化它.
主要是你的灵活性会松动.你会得到很多语义上的头痛和初始化和构造的松散分离(通过加入__new__ andinit我们将结构和初始化结合到一个步骤......).我们来看看下面的代码片段:
class A(object):
some_property = 'some_value'
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls, *args, **kwargs)
obj.some_property = cls.some_property
return obj
class B(A):
some_property = 2
def __new__(cls, *args, **kwargs):
obj = super(B, cls).__new__(cls)
return obj
Run Code Online (Sandbox Code Playgroud)
将__init__行动转移到的后果__new__:
B之前初始化A:当您使用__new__方法而不是__init__创建B的新实例的第一步是调用A.__new__副作用时,您无法在初始化B之前A初始化(访问并为新B实例分配一些属性).使用可以__init__提供这种灵活性.
对初始化顺序的松散控制:让我们假设你B_N继承了两个类(A_N1,A_N2),现在你将错过控制初始化新实例B_N的顺序(你要初始化实例的顺序是什么?这可能是问题......什么是奇怪的.)
属性和方法混乱:你会错过访问A.some_property(cls等同于B实例化新实例B.但是直接访问A.some_property是可能的,但我的猜测至少很奇怪,通过类名访问类中的属性而不是使用classmethods).
您无法为此创建新的实例或实现特殊逻辑来重新初始化现有实例(感谢@platinhom的想法)
__init__做什么__new__不可以?没有__new__不能在__init__其中__init__执行的操作,因为执行的操作是可以执行的操作的子集__new__.
来自Python Docs,Pickling和unpickling普通类实例#obob的有趣时刻.getinitargs关于什么时候__init__可能有用:
当pickle类实例被unpickled时,通常不会调用其init()方法.
您可以在 中做的一切__init__也可以在 中完成__new__。
那么,为什么要使用 呢__init__?
因为您不必将实例存储在变量中(obj在示例代码中),然后再费心返回它。您可以专注于您真正想做的事情 - 初始化可变对象。