Python中在元类动态添加的方法内正确调用super的方式是什么?
问题原因
Python 3 的无参super()依赖编译器在类定义体的静态上下文中,为方法自动注入名为__class__的闭包单元格变量,指向方法所属的类。你在元类__new__方法内部嵌套定义test函数时,test的定义上下文不属于任何类的定义体,编译器不会自动注入__class__变量,因此无参super()无法推断出要查找的父类位置,触发第一个TypeError。
你修改后的super(cls, self)写法逻辑是完全正确的:闭包捕获了当前元类创建的类cls,super会从cls在实例的MRO中的下一个位置开始查找test方法。第二个AttributeError属于预期报错,因为A的父类object没有实现test方法,只要父类存在对应方法就能正常运行。
优雅使用无参super()的方案
如果希望用无参super()的写法,可以手动为动态生成的方法创建__class__闭包变量,示例如下:
class FooMeta(type): def __new__(mcls, name, bases, attrs): __class__ = None def test(self): nonlocal __class__ return super().test() attrs["test"] = test # 创建完类后给__class__赋值 cls = super().__new__(mcls, name, bases, attrs) __class__ = cls return cls
这里通过nonlocal声明让编译器为test函数生成__class__闭包单元格,类创建完成后手动给单元格赋值为当前类,无参super()就能正常识别到所属类,不需要额外传参。
方案选型建议
- 如果追求代码可读性和兼容性,
super(cls, self)是最稳妥的写法,没有语法黑魔法,所有Python 3版本都支持,逻辑直观易懂。 - 如果追求写法简洁,可以用上述手动注入
__class__的方案,代码运行效果和显式传参完全一致。
内容的提问来源于stack exchange,提问作者Woody Huang
相关产品推荐
相关产品推荐

