类内使用双下划线装饰器触发Name mangling的解决方案咨询
在类中使用模块级双下划线开头的装饰器
这个问题的根源在于Python的**名称改写(name mangling)**机制:当你在类内部使用双下划线__开头的标识符时,Python会自动将其重命名为_类名__标识符的格式,目的是避免子类意外覆盖父类的私有属性/方法。所以当你在类A里写@__decorator时,Python实际会去查找_A__decorator,但你的装饰器是定义在模块层面的__decorator,自然就会抛出NameError。
要在保留双下划线命名规范的前提下解决这个问题,有几种可行的方法:
方法1:通过globals()直接引用模块级命名空间
globals()函数会返回当前模块的全局命名空间字典,我们可以直接从中取出模块级的__decorator,这样就能避开类内部的名称改写:
# 模块级的双下划线装饰器 def __decorator(fn): return fn class A(object): # 直接从全局命名空间获取装饰器 @globals()['__decorator'] def test(self): return 1 print(A().test()) # 输出:1
方法2:借助模块自身引用
如果你的脚本是主模块(即__name__ == '__main__'),也可以通过__import__获取模块自身,再引用装饰器:
def __decorator(fn): return fn class A(object): @__import__('__main__').__decorator def test(self): return 1 print(A().test()) # 输出:1
这种方法不如globals()简洁,但在一些特殊场景下也能生效。
方法3:提前绑定到非双下划线变量(折中方案)
如果你觉得上面的写法不够直观,也可以在类定义前把双下划线装饰器赋值给一个普通变量,然后在类里使用这个变量——虽然这会多一个别名,但能保持装饰器本身的双下划线命名:
def __decorator(fn): return fn # 绑定到普通变量 _decorator_alias = __decorator class A(object): @_decorator_alias def test(self): return 1 print(A().test()) # 输出:1
以上几种方法都能让你在类内部正确引用模块级的双下划线装饰器,根据自己的代码场景选择合适的即可。
内容的提问来源于stack exchange,提问作者jabozzo
相关产品推荐
相关产品推荐

