Python __name__ mangling机制下双下划线属性访问逻辑疑问
Python双前导下划线名称修饰实现逻辑
你观察到的现象本质是Python的双下划线名称修饰是编译期语法转换,而非运行时属性查找逻辑,整个过程和对象本身的属性存储没有关系,具体规则如下:
名称修饰的触发时机与转换规则
- 当Python编译器处理类定义体的代码时,会自动扫描所有符合规则的标识符:以至少2个前导下划线开头、至多1个尾随下划线结尾(排除前后均为双下划线的魔法方法,比如
__init__、__str__这类特殊方法不会被处理)。 - 对命中规则的标识符,编译器会直接将其重写为
_当前类名__原标识符名的格式,再生成对应的字节码。 - 你代码中
__init__方法里的self.__args = a,在编译阶段就已经被替换成了self._A__args = a,所以运行时实际给实例绑定的属性名就是_A__args,这也是dir(self)输出里只有_A__args、没有__args的根本原因——运行时从来就不存在名为__args的实例属性。
类内部访问self.__args正常生效的原因
- 类定义内部所有对
__args的引用,同样会在编译阶段被统一替换为_A__args。你在args属性方法里写的self.__args,实际运行时执行的是self._A__args的属性查找,自然能正常拿到值,和运行时是否存在__args这个属性名没有任何关系。 - 这种转换是严格限定在类定义体范围的:如果在类外部的代码里写
obj.__args,由于这段代码不属于类A的定义体,编译器不会对这里的__args做重写,运行时就会真的去实例上查找__args属性,最终抛出AttributeError。
补充验证
你可以直接在类外部访问修饰后的属性名验证逻辑:
obj = A("check") print(obj._A__args) # 直接输出check,和类内部访问self.__args的效果完全一致 # print(obj.__args) # 取消注释运行会抛出AttributeError: 'A' object has no attribute '__args'
内容的提问来源于stack exchange,提问作者user5319825
相关产品推荐
相关产品推荐

