访问 Python 中 class 的**私有**变量
Access to **private** variables of a class in Python
我了解 Python 不明确支持 class 中的私有变量。但是,请考虑以下程序:
class AClass(object):
def __init__(self, x):
self.__x = x
class BClass(object):
def __init__(self, x):
self.__x = x
# _____________________________________________________________________________
aClass = AClass(10)
bClass = BClass(10)
aClass.__x = 15
print (aClass.__x)
##bClass.__x = 20
print (bClass.__x)
上面的程序,会产生如下错误:
AttributeError: 'BClass' 对象没有属性 '__x'
但是,如果代码的倒数第二行没有被注释掉,它会在没有错误的情况下执行。
如果有人可以澄清似乎不一致的地方,并且如果有解释此行为的 PEP,我将不胜感激。
此致。
屋宇署
这是因为以双下划线开头的变量被命名为“保护”它们。如果您检查 bClass
的字典,您会看到:
>>> print(bClass.__dict__)
{'_BClass__x': 10, '__x': 20}
_BClass__x
(我称它为对象变量)是由对象本身创建的,因此它的名字是错位的。 __x
是在 class(a) 的 外部 创建的,这就是为什么它有一个 non-mangled名称,以及为什么只用 __x
.
就可以访问它
要访问这两种类型的对象变量,您可以使用:
print (aClass._AClass__x)
print (bClass._BClass__x)
但我不确定这有多可靠。我 am 确信这是你可能不应该做的事情,因为它破坏了封装:-)
事实上,虽然我说了 mangling 是由对象完成的,但我想确保你理解它不是在实例化对象时完成的。实际的修改发生在 编译代码时, 如果你反汇编你可以看到:
>>> import dis
>>> dis.dis(AClass)
Disassembly of __init__:
3 0 LOAD_FAST 1 (x)
2 LOAD_FAST 0 (self)
4 STORE_ATTR 0 (_AClass__x)
6 LOAD_CONST 0 (None)
8 RETURN_VALUE
STORE_ATTR
字节码实际上知道使用错位名称。
(a)而且和object变量有很大区别,以后你会发现很苦恼尝试在成员函数中使用 __x
并发现它没有被外部代码更改:-)
我了解 Python 不明确支持 class 中的私有变量。但是,请考虑以下程序:
class AClass(object):
def __init__(self, x):
self.__x = x
class BClass(object):
def __init__(self, x):
self.__x = x
# _____________________________________________________________________________
aClass = AClass(10)
bClass = BClass(10)
aClass.__x = 15
print (aClass.__x)
##bClass.__x = 20
print (bClass.__x)
上面的程序,会产生如下错误: AttributeError: 'BClass' 对象没有属性 '__x'
但是,如果代码的倒数第二行没有被注释掉,它会在没有错误的情况下执行。
如果有人可以澄清似乎不一致的地方,并且如果有解释此行为的 PEP,我将不胜感激。
此致。
屋宇署
这是因为以双下划线开头的变量被命名为“保护”它们。如果您检查 bClass
的字典,您会看到:
>>> print(bClass.__dict__)
{'_BClass__x': 10, '__x': 20}
_BClass__x
(我称它为对象变量)是由对象本身创建的,因此它的名字是错位的。 __x
是在 class(a) 的 外部 创建的,这就是为什么它有一个 non-mangled名称,以及为什么只用 __x
.
要访问这两种类型的对象变量,您可以使用:
print (aClass._AClass__x)
print (bClass._BClass__x)
但我不确定这有多可靠。我 am 确信这是你可能不应该做的事情,因为它破坏了封装:-)
事实上,虽然我说了 mangling 是由对象完成的,但我想确保你理解它不是在实例化对象时完成的。实际的修改发生在 编译代码时, 如果你反汇编你可以看到:
>>> import dis
>>> dis.dis(AClass)
Disassembly of __init__:
3 0 LOAD_FAST 1 (x)
2 LOAD_FAST 0 (self)
4 STORE_ATTR 0 (_AClass__x)
6 LOAD_CONST 0 (None)
8 RETURN_VALUE
STORE_ATTR
字节码实际上知道使用错位名称。
(a)而且和object变量有很大区别,以后你会发现很苦恼尝试在成员函数中使用 __x
并发现它没有被外部代码更改:-)