2012-05-29 38 views
4

下面的代码生成错误:Python的父类儿童私有变量的访问

class A(object): 
    def say_something(self): 
     print (self.foo) 
     print(self.__bar) 

class B(A): 

    def __init__(self): 
     self.foo='hello' 
     self.__something='world' 


test=B() 
test.say_something() 

印刷的“你好”是成功的,但“世界”生成以下错误:

print(self.__bar) 
AttributeError: 'B' object has no attribute '_A__bar' 

我对此我感到惊讶,我希望我的父类有一个方法,可以访问其子级保证的私有属性。有没有解决这个问题的标准方法?

附加问题:所以,如果我为一个属性使用单个下划线,从不同的对象中使用它会不会是错误的?是一个单独的下划线说“我会使用这个,但你的用户不应该”,或者甚至应该让开发者把它看作是私有的。请问这段代码是不好的风格:

class A(object): 
    def __init__(self): 
     self._foo='bar' 

Class B(object): 
    def __init__(self): 
     a=A() 
     b=A._foo 
+0

您可能会发现以下问题很有用:[Python中对象名称之前的单下划线和双下划线的含义](http://stackoverflow.com/questions/1301346/the-meaning-of-a -single-and-a-double-underscore-before-an-object-name-in-python) –

回答

9

您可以使用self._B__something来访问它。但是,这不是你应该做的。正确的解决方案是将__bar重命名为_bar

double-underscore name mangling背后的想法是为了避免与子类/超类发生冲突 - 它并不意味着用于私有变量。如果一个变量应该被认为是私人的/内部的,用一个下划线作为前缀。这不会导致任何特殊处理,但是每个python开发人员都会知道它不是包含该变量的类/模块的公共API的一部分。

+0

没错。名称修改机制的意图是准确地获得OP在这里看到的行为。它的意思是让一个成员元素链接到1并且只有1个作用域。 –

+0

明白了。我在这里找到了和你说的一样的东西http://docs.python.org/tutorial/classes.html我想对于没有什么是真正私人的想法我还是有点不舒服。 –

+0

那么,即使是在具有“真实”私有变量的语言中,总是有方法(反射或混淆内存)来访问它们。 Python简单地假定程序员很聪明,所以它不会真正实施私有变量。 – ThiefMaster

-1

我怀疑你缺少代码中的东西..我没有看到__bar在任何A类或B类..

+6

在StackOverflow上,我们使用适当的英文,即“你”和“是”而不是“u”和“r”。 – ThiefMaster

1

它的名字改编。任何以双下划线开头的成员都会在Python中获取名称。您的代码可以与任何其他成员一起使用,只要它们没有以双下划线开头。