0

我有一个 python 模块,m1。

# m1.py
class C1(object):
    def __init__(self):
        self.__pri = 10
        self._pro = 5
        self.pub = 1

然后在bpython中,

>>> import m1
>>> c = m1.C1()
>>> c.__pri
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'C1' object has no attribute '__pri'
>>> c._pro
5
>>> c.pub
1
>>> dir(c)
['_C1__pri', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_pro', 'pub']
>>> c._C1__pri
10

我认为python中没有私有变量的概念。我们现在如何解释这种行为?

编辑:我期待直接访问 c.__pri 但事实证明这name mangling阻止了我这样做,如下面的回答。谢谢大家!

4

3 回答 3

5

双下划线将类名与属性相混淆,前缀为单个下划线

    c._C1__pri

允许访问该属性。有点像伪隐私,但它还有其他用途。我不确定你期望会发生什么c.__private。我认为您打算这样做,c.__pri尽管结果是相同的。

__pri属性不是私有的,因为它可以在类之外访问,只需额外添加几个字符即可。

正如下面提到的 jadkik94,这并不是要使其无法访问,而是向另一个程序员发出信号,表明他们不应该使用该属性。

仅供参考,这可能会派上用场是在使用继承时

class Parent: 
    def __method(self): 
        print 'Parent method'

class Child(Parent): 
    def __method(self): 
        print 'Child method'

>>> c = Child()
>>> c._Child__method()
Child method
>>> c._Parent__method()
Parent method

双下划线可防止名称被意外覆盖(并非经常出现这种情况)。

于 2012-12-26T15:21:43.030 回答
1

名称修改

这提供了一种声明私有成员的方法。

这种双下划线名称修饰有助于防止覆盖子类中的内部私有变量。

表明不应使用成员变量的典型方法是在其前加一个下划线,尽管这只是一个约定。

于 2012-12-26T15:22:09.027 回答
1

您正在观察的是name mangling,其中具有两个前导下划线和最多一个尾随下划线的变量的名称被重命名以防止与子类发生意外冲突并防止临时黑客修改私有字段。

但是,很容易在修改后确定变量的名称是什么,因此它不会挫败确定的病态用户。

于 2012-12-26T15:22:35.697 回答