我正在学习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__
不执行任何初始化,因此也可以省略超类构造函数调用。