-2

I am learning python classes and could not understand below behavior:

In below example, I am extending built-in str class:

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

In below example, I am extending a user-defined class 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()

Why do we need to give self as argument in 2nd example in calling __init__ of super class, while there is no need to give self in calling str's __init__.

4

1 回答 1

2

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


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

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

str实现__new__,但继承__init__object. 当你覆盖__init__并打电话str.__init__时,你真的在​​打电话object.__init__

当您调用 时str.__init__(u_str),您实际上是在object.__init__调用u_str错误的对象,而不是 for 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)or super().__init__()。由于object.__init__不进行任何初始化,您也可以省略超类构造函数调用。

于 2020-01-26T08:45:16.203 回答