使用__的Python“隐藏”方法

时间:2012-08-24 21:47:40

标签: python oop inheritance

今天我看到 - python将_$CLASSNAME$添加到名称为__的方法中。

简单示例:

>>> class A:  
...     def a(self):  
...         self.b()  
...     def b(self):  
...         print('A.b')  
...           
>>> class B(A):  
...     def b(self):  
...         print('B.b')  
...           
>>> B().a()  
B.b

那项工作,但是:

>>> class A:  
...     def a(self):  
...         self.__b()  
...     def __b(self):  
...         print('A.b')  
...           
>>> class B(A):  
...     def __b(self):  
...         print('B.b')  
...           
>>> B().a()  
A.b

为什么呢?我不知道,所以我给了它。这是:

>>> print([fn for fn in dir(B) if fn[-2:] != '__'])
['_A__b', '_B__b', 'a']

为什么python会这样做?有没有办法绕过那个?

2 个答案:

答案 0 :(得分:11)

虽然python没有严格执行这一操作,但双下划线的命名约定意味着“私有”,而单个下划线意味着“受保护”。

双下划线旨在通过使用相同的名称来保护子类不会导致错误。通过按类名对它们进行命名,定义类可以确保其变量保持有效。

单个下划线意味着子类可以自由访问和修改那些与超类共享的相同属性。

两种形式建议任何外部类都不应该访问这些。

class A(object):

    __private = 'private'
    _protected = 'protected'

    def show(self):
        print self.__private 
        print self._protected

class B(A):
    __private = 'private 2'
    _protected = 'protected 2'

a = A()
a.show()
#private
#protected

b = B()
b.show()
#private
#protected 2

此示例显示即使类B定义了新的__private,它也不会影响继承的show方法,该方法仍然访问原始的超类属性。然而,_protected被修改,超类show方法反映了这一点,因为它们是相同的属性。

答案 1 :(得分:9)

它被称为名称修改,用于防止与父类和子类的意外名称冲突。你不能(也不应该,很多完美的代码使用它)禁用它。你可以规避它,但你不应该这样做(它非常难看,你可以避免它,当你需要访问它时,你不应该首先允许名称修改)。只需使用单个下划线即可在任何地方使用您想要使用的私有函数。

请参阅tutorial,但忽略对此的任何引用,表示“私有”变量。这不是它的用途,除非你在C ++ / Java / C#/ ... private变量中使用private(与子类可见的protected相反)隐藏在儿童班级。即便如此,这也是一个有缺陷的类比。