如何带参数正确调用Python中的super()?
问题:super()带参数调用时的递归错误与正确用法
我有一个线性继承的类层次结构A、B、C,三者共享同名方法m,但方法的签名和类型(静态方法、类方法、实例方法)各不相同,子类的实现依赖父类方法的返回结果。因为需要动态创建对象,必须使用super()的完整签名调用,但这里出现了问题。
零参数super()可正常运行
class A: @staticmethod def m(): return 'A.m()' class B(A): @classmethod def m(cls): return super().m() + ' ... & from B.m()' class C(B): def m(self, text): return super().m() + f' ... & from C().m("{text}")' print(C().m("XXX")) # 输出:A.m() ... & from B.m() ... & from C().m("XXX")
带参数super()触发递归错误
当尝试使用完整签名的super()时,代码触发了RecursionError:
class A: @staticmethod def m(): return 'A.m()' class B(A): @classmethod def m(cls): return super(cls, cls).m() + ' ... & from B.m()' # <- 触发RecursionError class C(B): def m(self, text): return super(type(self), self).m() + f' ... & from C().m("{text}")' print(C().m("XXX"))
报错信息:
File "path_to_file.py", line XY, in m return super(cls, cls).m() + ' ... & from B.m()' ^^^^^^^^^^^^^^^^^^^ [Previous line repeated 995 more times] RecursionError: maximum recursion depth exceeded
抽象示例(同样问题)
class A: def m(self): return f"A().m from {type(self).__name__}()" class B(A): def m(self): return super(?, ?).m() + f" & B().m from {type(self).__name__}()" class C(B): def m(self): return super(type(self), self).m() + f" & C().m from {type(self).__name__}()" print(C().m()) # 期望输出:A().m from C() & B().m from C() & C().m from C()
解决方法
核心原因
递归错误的本质是:使用super(cls, cls)(类方法中)或super(type(self), self)(实例方法中)时,第一个参数是当前对象/类的实际类型(可能是子类),导致super代理在MRO中跳过的是子类而非当前定义方法的类,最终循环调用当前方法。
正确写法
无论类方法还是实例方法,完整签名的super()第一个参数都应该写当前方法所在的类,而非动态获取的类型:
修复第一个示例
class A: @staticmethod def m(): return 'A.m()' class B(A): @classmethod def m(cls): # 第一个参数写当前类B,而非动态的cls return super(B, cls).m() + ' ... & from B.m()' class C(B): def m(self, text): # 第一个参数写当前类C,而非type(self) return super(C, self).m() + f' ... & from C().m("{text}")' print(C().m("XXX")) # 输出:A.m() ... & from B.m() ... & from C().m("XXX")
修复抽象示例
class A: def m(self): return f"A().m from {type(self).__name__}()" class B(A): def m(self): return super(B, self).m() + f" & B().m from {type(self).__name__}()" class C(B): def m(self): return super(C, self).m() + f" & C().m from {type(self).__name__}()" print(C().m()) # 输出:A().m from C() & B().m from C() & C().m from C()
原理说明
- 类方法中:
super(B, cls)会在cls的MRO中跳过B,直接查找父类A的方法,避免因cls是子类(如C)导致的递归。 - 实例方法中:
super(C, self)会在self的MRO中跳过C,查找父类B的方法,即使后续出现C的子类,也不会触发递归。
内容的提问来源于stack exchange,提问作者cards
相关产品推荐
相关产品推荐

