首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调用fractions.Fraction子类中的超级()fractions.Fraction(*args,**kwargs)只接受要初始化的实例

调用fractions.Fraction子类中的超级()fractions.Fraction(*args,**kwargs)只接受要初始化的实例
EN

Stack Overflow用户
提问于 2022-07-29 17:47:31
回答 1查看 78关注 0票数 3
代码语言:javascript
复制
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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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__

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73169218

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档