有这段代码:
class A:
__x = 2
def f(self):
print(dir(self)) # there is attribute _A__x, but not __x
print(self.__x) # prints 2
print(self._A__x) # prints 2
x = A()
x.f()
print(x.__x) # AttributeError: 'A' object has no attribute '__x'
为什么在__x
之类的方法中允许访问self.__x
变量,但不在此方法之外?我知道带有两个下划线的名称已被破坏,但问题是什么是特殊的,以便这个未编译的版本在方法中工作尽管self
仅将版本作为属性进行了修改。
编辑:
我注意到,如果某个属性添加到名称为_A__name
的类中,例如:
class A:
_A__y = 3
def f(self):
print(self.__y) # prints 3
print(self._A__y) # prints 3
x = A()
x.f()
然后在类内部,似乎当例如解释器查找变量__y
时,他也可以使用_A__y
名称,因此前缀_A
似乎与C ++中的范围解析类似比如A::
。但我不确定它的工作原理。
因此原始问题可以延伸为什么在这种情况下self.__y
与self._A__y
具有相同的效果,仅定义了_A__y
?
答案 0 :(得分:4)
以两个前导下划线命名的属性被“隐藏”以供在类之外使用(实际上未在下面看到)。它与其他语言中的私有属性类似。
重要的是,无法使用x.__x
从课堂外访问该属性,但可以使用{{1}访问该属性}。在课程内部,您可以使用(如示例中所示)两种方式。
在其他语言(如C ++)中,您会将x._A__x
声明为私有,而您可以在课程中将其用作__x
,而在外部则不能。{在python中它是类似的,因为你在里面也使用__x
,在外面你不应该使用它。
查看here以获取此行为的文档。
答案 1 :(得分:1)
self.__x
将被修改并转入self._A__x
,这就是它的原因。 Mangling只在类定义中的代码中完成。