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

推荐答案

太长,读不下go 了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) doesself).

但实际上你有一个更紧迫的问题.拥有自己的__init__是可以的,但有限制.您无法初始化Fraction,因为这是在调用__init__之前的__new__中完成的.当给定参数时,你不能调用Fraction.__init__,它除了爆炸之外什么都不做.您可以向对象添加其他属性,但仅此而已.但其他奇怪的事情也会发生.除非重写__add__之类的方法,否则它们将返回原始Fraction类型的对象,因为正在调用的是__new__.当您的父类使用__new__时,您真的希望重写该__new__.

Python相关问答推荐

通过优化空间在Python中的饼图中添加标签

重新匹配{ }中包含的文本,其中文本可能包含{{var}

Python上的Instagram API:缺少client_id参数"

不理解Value错误:在Python中使用迭代对象设置时必须具有相等的len键和值

Mistral模型为不同的输入文本生成相同的嵌入

在Python中管理打开对话框

如何在python polars中停止otherate(),当使用when()表达式时?

如何获得每个组的时间戳差异?

OR—Tools中CP—SAT求解器的IntVar设置值

从spaCy的句子中提取日期

python中字符串的条件替换

字符串合并语法在哪里记录

使用Python和文件进行模糊输出

旋转多边形而不改变内部空间关系

如何使用两个关键函数来排序一个多索引框架?

pandas:在操作pandora之后将pandora列转换为int

用fft计算指数复和代替求和来模拟衍射?

Python OPCUA,modbus通信代码运行3小时后出现RuntimeError

Python:从目录内的文件导入目录

如果列包含空值,则PANAS查询不起作用