为什么在 Python 中扩展不可变 class 时需要使用 __new__()?
Why do we need to use __new__() when extending a immutable class in Python?
我正在阅读 Mastering Object-Oriented Python 这本书。在书中谈到 __new__
方法和不可变对象的部分,它说类似 __new__()
方法用于扩展不可变 classes,其中 __init__()
方法不能轻易被覆盖。它还给出了一个例子如下
class Float_Fail(float):
def __init__(self, value, unit):
super().__init__(value)
self.unit = unit
f = Float_Fail(6.5, "knots")
TypeError Traceback (most recent call last)
<ipython-input-2-9511e6ca03be> in <module>()
----> 1 f = Float_Fail(6.5, "knots")
TypeError: float() takes at most 1 argument (2 given)
我很好奇为什么 float 会报这个错误。我的意思是,我们可以像这样初始化一个浮点数:
f = float(1.1)
这是否意味着 float
class 的 __init__()
方法将数字作为第二个参数。如果不是,那么 Python 中如何实现不可变 class 的初始化?
在 __init__
方法运行时,对象已经存在。由于该对象是不可变的,因此无法在 __init__
.
中更改其值
如果你做 MyClass(1)
,那么 1
确实作为参数传递给 __init__
。但是 __new__
在 __init__
之前被调用,所以 1
是 首先 作为参数传递给 __new__
。您看到的错误是因为您没有覆盖 __new__
,所以调用了继承的 float.__new__
,它不接受您的额外参数。它甚至没有机会尝试调用 __init__
,因为它在尝试调用 __new__
.
时失败了
这在 the documentation 中有解释。正如那里明确指出的那样,你在启动 class 时传递的参数(例如,MyClass(1)
中的 1
)被传递给 both __new__
和 __init__
,按此顺序。
我正在阅读 Mastering Object-Oriented Python 这本书。在书中谈到 __new__
方法和不可变对象的部分,它说类似 __new__()
方法用于扩展不可变 classes,其中 __init__()
方法不能轻易被覆盖。它还给出了一个例子如下
class Float_Fail(float):
def __init__(self, value, unit):
super().__init__(value)
self.unit = unit
f = Float_Fail(6.5, "knots")
TypeError Traceback (most recent call last)
<ipython-input-2-9511e6ca03be> in <module>()
----> 1 f = Float_Fail(6.5, "knots")
TypeError: float() takes at most 1 argument (2 given)
我很好奇为什么 float 会报这个错误。我的意思是,我们可以像这样初始化一个浮点数:
f = float(1.1)
这是否意味着 float
class 的 __init__()
方法将数字作为第二个参数。如果不是,那么 Python 中如何实现不可变 class 的初始化?
在 __init__
方法运行时,对象已经存在。由于该对象是不可变的,因此无法在 __init__
.
如果你做 MyClass(1)
,那么 1
确实作为参数传递给 __init__
。但是 __new__
在 __init__
之前被调用,所以 1
是 首先 作为参数传递给 __new__
。您看到的错误是因为您没有覆盖 __new__
,所以调用了继承的 float.__new__
,它不接受您的额外参数。它甚至没有机会尝试调用 __init__
,因为它在尝试调用 __new__
.
这在 the documentation 中有解释。正如那里明确指出的那样,你在启动 class 时传递的参数(例如,MyClass(1)
中的 1
)被传递给 both __new__
和 __init__
,按此顺序。