【问题标题】:How to access `conventional` private variables in python?如何在 python 中访问“常规”私有变量?
【发布时间】:2012-12-26 15:17:55
【问题描述】:

我有一个 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 阻止我这样做,如下面的回答。谢谢大家!

【问题讨论】:

  • 你想从我们这里得到什么?)是的,它确实像这样工作。
  • 你在这里期待什么?
  • 这已被广泛记录 (docs.python.org/2/tutorial/…),请在提出此类问题之前进行一些研究。
  • @l4mpi 好吧,我做了功课并进行了研究,但很不幸错过了这一点。 @alexvassel问题显然是你如何解释这一点,更不用说它是这样工作的。那里的人们亲切地提到了name mangling

标签: python variables accessor private-members


【解决方案1】:

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

    c._C1__pri

允许访问该属性。有点像伪隐私,但它还有其他用途。 我不确定你对c.__private 的期望。我认为你的意思是 c.__pri 虽然结果是一样的。

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

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

FYI 另一个可能派上用场的时候是使用继承时

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

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

【讨论】:

  • 你应该提到,这个的全部意义不是意味着像“你不能使用这个”那样是私有的,但是你“不应该使用这个”是私有的这个”
  • @jadkik94 我喜欢你的评论。非常说。谢谢
  • @xhainingx 非常感谢您详细解答。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    Name Mangling

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

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

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

    【讨论】:

      猜你喜欢
      • 2020-12-11
      • 2011-03-02
      • 2015-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多