为什么在 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__,按此顺序。