from fractions import Fraction
class F1(Fraction):
def __init__(self, *args, **kwargs):
Fraction.__init__(*args, **kwargs)
class F2(Fraction):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Fraction(1, 10) # Fraction(1, 10)
F1(1, 10) # F1(1, 10)
F2(1, 10) # TypeError: object.__init__() takes exactly one argument (the instance to initialize)这是怎么发生的?有人能详细介绍一下超级功能吗?
Python版本: 3.8.10
发布于 2022-07-29 19:31:49
Fraction使用__new__而不是__init__。
Python对象分两个步骤组装。首先,使用__new__创建它们,然后用__init__初始化它们。通常,我们使用默认的object.__new__来创建一个新的空对象,然后对需要执行的任何特殊操作重写__init__。
但是有些类希望通过实现自己的__new__来控制对象创建步骤。对于Fraction这样的不可变类尤其如此。Fraction.__new__返回它自己的超类的一个对象,当发生这种情况时,python将完全跳过调用__init__。在Fraction的例子中,它的__init__实际上就是object.__init__,它只接受单个self参数,并且不执行任何操作就返回。它从来就不是用来叫的。
当您实现F1.__init__时,您有一个bug,这个bug掩盖了问题。当直接调用超类方法时,需要在调用中放入self参数。你应该做Fraction.__init__(self, *args, **kwargs)的。如果这样做,您将得到与F2情况相同的错误(因为super().__init__(*args, **kwargs)确实添加了self)。
但你真的有一个更紧迫的问题。拥有自己的__init__是可以的,但有限制。您无法初始化Fraction,因为这是在调用__init__之前在__new__中完成的。您不能调用Fraction.__init__,它只会在给定参数时爆炸。您可以向对象添加其他属性,但仅此而已。但其他奇怪的事情也会发生。除非重写像__add__这样的方法,否则它们将返回原始Fraction类型的对象,因为这是要调用的__new__。当父类使用__new__时,您确实希望重写该__new__。
https://stackoverflow.com/questions/73169218
复制相似问题