【问题标题】:Difference between calling __init__() of build-in class and __init__() of user-defined class调用内置类的__init__()和自定义类的__init__()的区别
【发布时间】:2020-01-26 07:39:00
【问题描述】:

我正在学习 python 类,但无法理解以下行为:

在下面的示例中,我正在扩展内置的str 类:

class uStr(str):
    def __init__(self,u_str):
        str.__init__(u_str)       #<<<------- no self is needed

    def underline(self):
        underlines = format('', '-^' + str(len(self)))
        return str.__str__(self) + '\n' + underlines

在下面的例子中,我正在扩展一个用户定义的类Fraction

from fraction import *

class MixedFraction(Fraction):
    def __init__(self, *args):
        Fraction.__init__(self, args[0], args[1])     #<<<-------self is needed

    def getWholeNum(self):
        return self.getNumerator() // self.getDenominator()

为什么在调用超类的__init__的第二个例子中我们需要给self作为参数,而在调用str__init__时不需要给self

【问题讨论】:

  • “不需要自我” - 是的。 __init__ 调用是错误的。令人困惑的是,您应该省略的参数实际上是 u_str

标签: python class python-object


【解决方案1】:

首先,您根本不需要那些__init__ 实现。您可以只继承超类实现。如果你确实需要自定义构造,那么对于uStr,你应该在__new__而不是__init__中进行。


str doesn't have 自己的__init__。它在__new__ 中进行所有初始化,因为str 实例是不可变的,并且在__init__ 中初始化将是可变的。 strobject 继承 __init__

object.__init__object.__new__ 有点奇怪。如果恰好覆盖了object.__init__object.__new__ 之一,那么如果给定参数(超出self)并且另一个忽略参数,则被覆盖的那个会引发错误,从而节省您必须提供无操作覆盖的工作.但是,如果两者都或都没有被覆盖,那么如果给定参数(超出self),两者都会抛出错误。您可以在源代码中的 big comment 中看到这一点。

str 实现 __new__,但从 object 继承 __init__。当您覆盖__init__ 并调用str.__init__ 时,您实际上是在调用object.__init__

当您调用str.__init__(u_str) 时,您实际上是在为u_str(错误的对象)而不是self 调用object.__init__。由于u_str 没有__init__ 覆盖(并且由于您只传递一个参数,它被解释为self),object.__init__ 默默地什么都不做。

当您调用 str.__init__(self, u_str) 时,您正在为 self 调用 object.__init__,但由于 self 已同时覆盖 __new____init__object.__init__ 抱怨 u_str 参数.

看起来您实际上根本不需要覆盖子类中的构造。如果这样做,自定义str 子类的构造的正确方法是覆盖__new__。如果出于某种奇怪的原因您必须调用str.__init__,正确的调用应该是str.__init__(self)super().__init__()。由于object.__init__ 不进行任何初始化,您也可以省略超类构造函数调用。

【讨论】:

  • 感谢 @user2357112 支持 Monica 的回答。我从答案中得到了一些想法,但我认为我仍然需要更深入地了解更多信息。
猜你喜欢
  • 2021-02-22
  • 1970-01-01
  • 2010-11-26
  • 2012-11-01
  • 2017-12-13
  • 1970-01-01
  • 2018-12-02
  • 1970-01-01
  • 2017-08-26
相关资源
最近更新 更多