带有私有继承的Python名称处理

时间:2019-02-13 17:52:17

标签: python python-2.7

我知道Python name mangling,但是在使用多重继承时遇到了意外的行为。例如:

class A(object):
  def __init__(self):
    self.__foo=1
  def bar(self):
    return self.__foo

class B(object):
  pass

class C(B):
  def __init__(self):
    self.test=1

class D(C,A):
  pass

print D().bar()

出现错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in bar
AttributeError: 'D' object has no attribute '_A__foo'

但是,如果我将“ D”的定义更改为:

class D(A,C):
  pass

有效。输出:

1 

此外,如果我从类“ C”中删除所有成员变量,则D作品的定义都将

class C(B):
  pass

class D1(A, C):
  pass

class D2(C, A):
  pass

print D1().bar()
print D2().bar()

输出:

1
1

有人能启发我这里发生了什么吗?我希望这些类定义中的任何一个都具有相同的行为。

1 个答案:

答案 0 :(得分:3)

在您的原始定义class D(C, A)中,对D.__init__的调用被解析为C.__init__,因此从未调用A.__init__并且从未创建__foo属性

在修改后的定义(class D(A, C)中,对D.__init__的调用被解析为A.__init__,这确实设置了__foo

调用父构造函数以确保实例已正确初始化很重要,并且与Java不同,必须显式调用父构造函数。

对于多重继承,如果使用super以确保调用每个类的__init__方法,则问题会更少。

class A(object):
    def __init__(self):
        super(A, self).__init__()
        self.__foo = 1

    def bar(self):
        return self.__foo


class B(object):
    pass


class C(B):
    def __init__(self):
        super(C, self).__init__()
        self.test = 1


class D1(C,A):
    pass


class D2(A,C):
    pass


# Both will print 1
print D1().bar()
print D2().bar()

只要所有类正确使用super,每个方法将被调用一次,无论方法解析顺序是D1的[C, B, A, object]还是D2的[A, C, B, object]