调用内置类的 __init__() 和用户定义类的 __init__() 之间的区别



我正在学习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__实现。你可以只继承超类实现。如果你真的需要自定义构造,那么对于uStr,你应该在__new__而不是__init__中完成。


str没有自己的__init__.它所有的初始化都是在__new__,因为str实例是不可变的,在__init__中初始化将是可变的。str继承了object__init__

object.__init__object.__new__有点奇怪。如果恰好object.__init__object.__new__中的一个被覆盖,那么被覆盖的参数在给定参数(超出self(时会抛出错误,而另一个忽略参数,以节省您必须提供无所事事覆盖的工作。但是,如果两者都或两者都没有被覆盖,那么如果给定参数(超出self个(,则两者都会抛出错误。您可以在源代码的大注释中看到这一点的解释。

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

当你调用str.__init__(u_str)时,你实际上是在object.__init__调用u_str,错误的对象,而不是self。由于u_str没有__init__覆盖(并且由于您只传递一个参数,该参数被解释为self(,因此object.__init__默默地不执行任何操作。

当你打电话给str.__init__(self, u_str)时,你是在object.__init__呼吁self,但由于self__new____init__都被覆盖了,object.__init__抱怨u_str论点。

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

相关内容

  • 没有找到相关文章