具有双下划线的Python方法名称被覆盖?

看看这个。 请注意,类B重写Aa()方法。

 In [1]: class A(object): ...: def __init__(self): ...: self.a() ...: def a(self): ...: print "Aa()" ...: ...: In [2]: class B(A): ...: def __init__(self): ...: super(B, self).__init__() ...: def a(self): ...: print "Ba()" ...: ...: In [3]: b = B() Ba() 

那里没有惊喜。

现在,看看这个。 请注意,现在被覆盖的方法是__a()

 In [7]: class A(object): ...: def __init__(self): ...: self.__a() ...: def __a(self): ...: print "A.__a()" ...: ...: In [8]: class B(A): ...: def __init__(self): ...: super(B, self).__init__() ...: def __a(self): ...: print "B.__a()" ...: ...: In [9]: b = B() A.__a() 

这种行为让我感到惊讶

任何人都可以解释为什么A.__a()被调用,而不是B.__a()

什么__special__关于__a

更新 :在阅读肖恩的答案后,我想看看是否可以重写名称mangled方法,并得到这个结果:

 In [11]: class B(A): ....: def __init__(self): ....: super(B, self).__init__() ....: def _A__a(self): ....: print "B._A__a()" ....: ....: In [12]: b = B() B._A__a() 

具有__ *模式的关键字是类专用名称。

http://docs.python.org/reference/lexical_analysis.html#reserved-classes-of-identifiers

引用:

当在类定义的上下文中使用时,这个类中的名称会被重写,使用一个强化的表单来帮助避免基类和派生类的“私有”属性之间的名称冲突

私人的名字(强调增加):

专用名称修改:当文本在类定义中出现的标识符以两个或更多下划线字符开始,并且不以两个或更多下划线结尾时,它被认为是该类的专用名称。 在为其生成代码之前,专用名称将转换为更长的forms。 转换在名称前面插入类名,删除前导下划线,并在类名前面插入一个下划线。 例如,名为Ham的标识符__spam将被转换为_Ham__spam 。 这种转换与使用标识符的语法上下文无关。 如果转换的名称非常长(超过255个字符),则可能会发生实现定义的截断。 如果类名只包含下划线,则不进行转换。

http://docs.python.org/reference/expressions.html#atom-identifiers

这意味着在幕后, B.__a()被转换成类似于B._B__a()

 In [1]: class A(object): ...: def __init__(self): ...: self.a() ...: def a(self): ...: print "Aa()" ...: ...: __str__ = a ...: In [2]: class B(A): ...: def __init__(self): ...: super(B, self).__init__() ...: def a(self): ...: print "Ba()" ...: ...: In [3]: b = B() print str(b) Aa() 

你需要在B中再次声明__str__