是否重写了带有双下划线的Python方法名称?

时间:2011-06-22 18:18:47

标签: python

看看这个。 请注意,课程B会覆盖A的{​​{1}}方法。

a()

没有惊喜。

现在,看看这个。 请注意,现在被覆盖的方法是In [1]: class A(object): ...: def __init__(self): ...: self.a() ...: def a(self): ...: print "A.a()" ...: ...: In [2]: class B(A): ...: def __init__(self): ...: super(B, self).__init__() ...: def a(self): ...: print "B.a()" ...: ...: In [3]: b = B() B.a()

__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__

更新 : 在阅读了Sean的回答后,我想看看是否可以覆盖名称损坏的方法并得到这个结果:

__a

2 个答案:

答案 0 :(得分:31)

带有__ *模式的

关键字是类私有名称。

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

引用:

  

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

私人名称修改(强调添加):

  

私有名称修改:当在类定义中以文本方式出现的标识符以两个或多个下划线字符开头并且不以两个或多个下划线结尾时,它被视为该类的私有名称。在为其生成代码之前,将私有名称转换为更长的形式。转换在名称前插入类名,删除前导下划线,并在类名前面插入单个下划线。 例如,名为Ham的类中出现的标识符__spam将转换为_Ham__spam 。此转换独立于使用标识符的语法上下文。如果转换后的名称非常长(超过255个字符),则可能会发生实现定义的截断。如果类名仅由下划线组成,则不进行转换。

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

这意味着在幕后,B.__a()会转换为类似B._B__a()

的内容

答案 1 :(得分:0)

In [1]: class A(object):
...:     def __init__(self):
...:         self.a()
...:     def a(self):
...:         print "A.a()"
...:
...:     __str__ = a
...:         

In [2]: class B(A):
...:     def __init__(self):
...:         super(B, self).__init__()
...:     def a(self):
...:         print "B.a()"
...:         
...:         

In [3]: b = B()
        print str(b)
   A.a()

您需要在 B 中再次声明__str__