在 Python 中访问类的**私有**变量
Posted
技术标签:
【中文标题】在 Python 中访问类的**私有**变量【英文标题】:Access to **private** variables of a class in Python 【发布时间】:2020-12-11 13:04:17 【问题描述】:我了解 Python 不明确支持类中的私有变量。但是,请考虑以下程序:
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 可以解释这种行为,我将不胜感激。
最好的问候。
BD
【问题讨论】:
【参考方案1】:这是因为以 dunder 开头的变量名称被修改以“保护”它们。如果你查看bClass
的字典,你会看到:
>>> print(bClass.__dict__)
'_BClass__x': 10, '__x': 20
_BClass__x
(我将其称为对象变量)是由对象本身创建的,因此它的名称不正确。 __x
是在类(a)外部创建的,这就是为什么它有一个未损坏的名称,因此您可以只使用__x
访问它.
要访问这两种类型的对象变量,您可以使用:
print (aClass._AClass__x)
print (bClass._BClass__x)
但我不确定这有多可靠。我我确定这是您可能不应该做的事情,因为它破坏了封装:-)
事实上,虽然我说重整是由对象完成的,但我想确保您理解它不是在实例化对象时完成的。实际的修改发生在代码被编译时,如果你反汇编你可以看到:
>>> 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) 它与对象变量非常不同,当您稍后尝试在成员函数,发现它没有被你的外部代码改变:-)
【讨论】:
我确实知道我已经使用 ``` print (dir(bClass))`` 进行了检查。我无法理解的是访问的不一致:写访问是无条件允许的,而读访问在执行写入后成为可能。 @user816270:读取仅在写入后才有效,因为在类之外,__x
在您创建它之前实际上并不存在(仅_<classname>__x
存在)。在执行 varname = "something"
之前尝试 print(varname)
没有什么不同。以上是关于在 Python 中访问类的**私有**变量的主要内容,如果未能解决你的问题,请参考以下文章