为什么这个超类在初始化期间不在子类中运行方法?

时间:2016-04-07 08:47:33

标签: python oop

为什么此代码不打印10

我期待超类在子类中调用__init_var方法。

class A:
    def __init__(self):
        self.__init_var()

    def __init_var(self):
        self.var = 1

class B(A):
    def __init__(self):
        A.__init__(self)

    def __init_var(self):
        self.var = 10

print(B().var)

1 个答案:

答案 0 :(得分:4)

您使用两个初始下划线命名方法__init_var,使其成为类私有方法。该名称被修改以确保子类不与其冲突。来自Reserved classes of identifiers section

  

__*
  类私有名称。当在类定义的上下文中使用时,此类别中的名称将被重写以使用损坏的表单来帮助避免基类和派生类的“私有”属性之间的名称冲突。

Identifiers (Names) section

  

私有名称修改:当在类定义中以文本方式出现的标识符以两个或多个下划线字符开头且不以两个或多个下划线结尾时,它被视为该类的私有名称。在为其生成代码之前,将私有名称转换为更长的形式。转换将在名称前面插入类名,删除前导下划线并插入单个下划线。例如,名为__spam的类中出现的标识符Ham将转换为_Ham__spam

因此A.__init_var重命名为A._A__init_varA.__init__()更改为A._A__init_var()。永远不会调用重命名的B._B__init_var()方法,因为它具有不同的名称:

>>> dir(A)
['_A__init_var', '__doc__', '__init__', '__module__']
>>> import dis
>>> dis.dis(A.__init__)  # disassemble the bytecode for A.__init__
  3           0 LOAD_FAST                0 (self)
              3 LOAD_ATTR                0 (_A__init_var)
              6 CALL_FUNCTION            0
              9 POP_TOP
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE
>>> dir(B)
['_A__init_var', '_B__init_var', '__doc__', '__init__', '__module__']

删除其中一个初始下划线,因此将其命名为_init_var

class A:
    def __init__(self):
        self._init_var()

    def _init_var(self):
        self.var = 11

class B(A):
    def __init__(self):
        A.__init__(self)

    def _init_var(self):
        self.var = 10