gpt4 book ai didi

python - 在 fractions.Fraction 子类中调用 super().__init__(*args, **kwargs) 只接受要初始化的实例

转载 作者:行者123 更新时间:2023-12-05 04:25:48 30 4
gpt4 key购买 nike

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)

这是怎么发生的?有人可以详细说明一下 super 功能吗?

Python 版本:3.8.10

最佳答案

TLDR; Fraction 使用 __new__ 而不是 __init__

Python 对象分两步组装。首先,它们是用 __new__ 创建的,然后用 __init__ 初始化。通常我们使用默认的 object.__new__ 来创建一个新的空对象,然后覆盖 __init__ 来处理任何需要完成的特殊事情。

但是有些类想通过实现自己的__new__来控制对象的创建步骤。对于像 Fraction 这样的不可变类尤其如此。 Fraction.__new__ 返回它自己父类(super class)的对象,当发生这种情况时,python 会完全跳过调用 __init__。对于 Fraction,它的 __init__ 实际上只是 object.__init__,它只接受单个 self 参数和什么都不做就直接返回。它永远不会被调用。

当您实现 F1.__init__ 时,您遇到了一个错误,这个错误掩盖了问题。直接调用父类(super class)方法时,需要在调用中放入self参数。你应该已经完成​​了 Fraction.__init__(self, *args, **kwargs)。如果你这样做了,你会得到与 F2 情况相同的错误(因为 super().__init__(*args, **kwargs) 确实 添加 self)。

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

关于python - 在 fractions.Fraction 子类中调用 super().__init__(*args, **kwargs) 只接受要初始化的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73169218/

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