gpt4 book ai didi

python - `__init__` 能做什么而 `__new__` 不能?

转载 作者:IT老高 更新时间:2023-10-28 22:12:35 25 4
gpt4 key购买 nike

在 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

可以像这样使用 __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

澄清问题范围:这不是关于如何使用 __init____new__ 或它们之间有什么区别的问题。这是一个关于如果从语言中删除 __init__ 会发生什么的问题。有什么会坏吗?有什么事情会变得更难或不可能吗?

最佳答案

注意 __new__ 和 __init__ 的区别

在解释缺少的功能之前,让我们回到 __new____init__ 的定义:

__new__ 是创建实例的第一步。它首先被调用,并负责返回您的类的新实例

但是,__init__ 不会返回任何内容;它只负责创建实例后对其进行初始化。

将 __init__ 替换为 __new__ 的后果

主要是你会失去灵 active 。你会遇到很多语义上的麻烦,以及初始化和构造的松散分离(通过加入 __new__ 和init,我们将把构造和初始化合并为一个步骤......)。让我们看一下下面的片段:

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

__init__ Action 移动到 __new__ 的后果:

  1. Initialize B before A:当你使用 __new__ 方法而不是 __init__ 你的第一个创建 B 的新实例的步骤是调用 A.__new__ 作为副作用,您无法在 A 初始化之前初始化 B (访问并分配一些属性到新的 B 实例)。 __init__ 的使用为您提供了这样的灵 active 。

  2. 对初始化顺序的松散控制:假设您现在有从两个类(A_N1A_N2)继承的 B_N你会错过对 B_N 的新实例的初始化顺序的控制(你要初始化实例的顺序是什么?这可能很重要......这很奇怪。)

  3. 属性和方法困惑:你会错过访问 A.some_property (cls 将等于 B 同时实例化 new B 的实例。但是直接访问 A.some_property 是可能的,但我猜通过类名而不是使用 访问类中的属性至少很奇怪类方法)。

  4. 如果不为此创建新实例或实现特殊逻辑,则无法重新初始化现有实例(感谢 @platinhom 的想法)

__init__ 能做什么而 __new__ 不能?

__new__ 中没有不能完成的 Action ,__init__ 中可以,因为 __init__ 执行的 Action 是一个子集 __new__ 可以执行的操作。

来自Python Docs, Pickling and unpickling normal class instances#object.getinitargs 的有趣时刻关于何时 __init__ 可能有用:

When a pickled class instance is unpickled, its init() method is normally not invoked.

关于python - `__init__` 能做什么而 `__new__` 不能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35452178/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com