Python内部类继承双下划线前缀外部类的问题解决方法
问题根因
这个报错来自Python的双下划线名称改写(Name Mangling) 机制:
- 只要标识符出现在类定义的代码块内,且满足「以2个及以上下划线开头、最多1个下划线结尾」的规则,Python在语法解析阶段就会静态对其重命名,规则是在名称前拼接
_外层类名,和这个标识符是属性、方法、还是要继承的父类没有关系。 - 在
Some_Category类体内写继承__Thing_Abstract时,解析器直接把这个名字改写成了_Some_Category__Thing_Abstract,根本不会用原名去全局作用域查找,自然会抛出找不到名称的错误。 - 之前测试的类方法内引用全局类能正常运行,核心原因是测试用的
A_Class1不是双下划线开头,不会触发静态名称改写,走的是正常的作用域查找逻辑。
补充说明:双下划线名称改写的设计初衷,是解决类继承场景下内部属性/方法的命名冲突问题,从设计上就不是给模块级全局类、全局变量使用的。
解决方案
方案1(推荐,符合Python规范)
不要给模块级全局类使用双下划线前缀,改用单下划线前缀标识模块内部私有类即可。单下划线是Python约定俗成的模块私有标识,不会触发名称改写,代码可读性最好:
class _Thing_Abstract: def __init__(self,var): self.var=var class Some_Category: class Thing(_Thing_Abstract): def printVar(self): print(self.var) def getType(self): return type(self.var)
方案2(兼容保留双下划线命名的场景)
如果因为特殊原因必须保留全局类的双下划线命名,可以通过globals()字典动态获取全局类对象——字符串形式的类名不会触发静态名称改写:
class __Thing_Abstract: def __init__(self,var): self.var=var class Some_Category: # 直接从全局作用域字典按原名取类对象,绕开名称改写 class Thing(globals()["__Thing_Abstract"]): def printVar(self): print(self.var) def getType(self): return type(self.var)
方案3(别名绕转)
也可以在类定义外先给双下划线全局类绑定一个不带双下划线的别名,在类体内用别名引用父类,本质也是绕开名称改写规则:
class __Thing_Abstract: def __init__(self,var): self.var=var # 定义无下划线前缀的别名 _BaseThing = __Thing_Abstract class Some_Category: class Thing(_BaseThing): def printVar(self): print(self.var) def getType(self): return type(self.var)
内容的提问来源于stack exchange,提问作者user18798042
相关产品推荐
相关产品推荐

