6

今天我看到 - 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']

为什么蟒蛇这样做?有没有办法绕过它?

4

2 回答 2

12

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

请参阅教程,但忽略对此表示“私有”变量的任何引用。这不是它的用途,除非您private在 C++/Java/C#/... 意义上使用对子类隐藏的private变量(与protected子类可见的变量相反)。即使这样,这也是一个有缺陷的类比。

于 2012-08-24T21:50:28.103 回答
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

这个例子表明,即使 classB定义了一个 new __private,它也不影响继承的show方法,它仍然访问原始的超类属性。_protected然而,被修改并且超类show方法反映了这一点,因为它们是相同的属性。

于 2012-08-24T21:57:56.303 回答