You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中为何super()()与super().__init__()效果不一致?

核心误区说明

你两个问题的根源是同一个认知错误:super()的返回值根本不是父类本身,而是一个专门实现MRO属性查找的代理对象,它的特殊逻辑只在.属性访问时触发,本身不具备父类/父类实例的所有特性。


问题1:为什么super()()无法调用父类__init__?

super()返回的是super类型的实例,这个类型本身没有实现__call__方法,所以你直接对super()加括号做调用操作时,会直接抛出TypeError: 'super' object is not callable,和你拿一个普通自定义类的、没实现__call__的实例直接调用是一个道理。

你之前认为super()等价于父类int,这个理解完全错误。正确的逻辑是:

  • 当你写super().__init__(value)时,.属性访问触发了super对象的代理逻辑:它会沿着类的MRO(方法解析顺序)链,找到父类中对应的__init__方法,绑定到当前实例self之后返回,这时候你调用这个拿到的方法,才是正确的父类初始化操作。
  • 如果你真的要直接拿父类调用,写法是int.__init__(self, value),但这种硬编码父类名的写法在多继承场景下会破坏MRO调用顺序,不推荐使用。

你的错误示例代码:

class My_Int(int):
    def __init__(self,value,extr_data=None):
        super()(value) # 错误:super对象本身不可调用
        self.extr_data=extr_data

x=My_Int(3)

修正后正确写法就是你提到的super().__init__(value)。


问题2:为什么len(super())报错,但super().__len__()可以正常运行?

这个问题的核心是Python内置函数的特殊方法查找规则:

对len()、str()这类C实现的内置函数,查找参数对应的特殊方法(如__len__)时,会直接读取参数所属类型的底层方法槽,不会走实例的自定义属性查找流程,自然也不会触发super对象的代理逻辑。

你写len(super())时,Python直接检查super这个类本身有没有实现__len__方法,发现没有就直接抛出TypeError: object of type 'super' has no len(),根本不会触发代理去查找父类list的__len__。

而你写super().__len__()时,是主动通过.做属性访问,这时候super的代理逻辑正常生效:顺着MRO找到list类的__len__方法,绑定到当前实例后调用,所以能正确返回长度4。

对应的测试代码:

class My_List(list):
    def some_method1(self):
        print(len(super())) # 错误:直接查super类本身的__len__,不存在

    def some_method2(self):
        print(super().__len__()) # 正确:属性访问触发super代理,找到list的__len__

x=My_List((1,2,3,4))

x.some_method2()
x.some_method1()

运行结果和你贴的一致:先打印4,再在调用some_method1时抛出类型错误。


总结

别把super()当成父类或者父类实例的替代品,它只是个带特殊属性查找规则的代理:

  • 只有对它做.属性访问操作时,它才会帮你沿MRO链查找父类的属性/方法
  • 它本身既不是可调用的类对象,也没有实现各类内置特殊方法,直接调用、直接传给内置函数做参数都会触发不符合预期的错误。

内容的提问来源于stack exchange,提问作者user18798042

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 22:18:42