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

在__init_subclass__中使用super()无法调用父类classmethod的问题

解决__init_subclass__中调用父类classmethod的报错问题

哈哈,这个坑我之前踩过!你遇到的AttributeError: 'super' object has no attribute 'foo',核心原因是super()在__init_subclass__里的用法和普通方法不一样,咱们一步步拆解:

为什么原来的写法会报错?

你写的super(cls)只传了一个参数,这会创建一个未绑定的super对象——它没有和任何类的上下文绑定,所以根本不会去cls的MRO序列里查找foo方法。哪怕cls.__mro__里明确有Foo,未绑定的super也无法识别到这个类方法,自然就抛出了属性不存在的错误。

正确的写法有哪些?

方法1:给super()传递两个参数(最推荐)

这是最符合Python设计意图的写法,能完美适配多继承场景:

class Foo:
    def __init_subclass__(cls):
        print('init', cls, cls.__mro__)
        super(cls, cls).foo()  # 传递子类cls作为两个参数
    @classmethod
    def foo(cls):
        print('foo')
class Bar(Foo):
    pass

这里的super(cls, cls)做了两件关键的事:

  • 第一个cls:告诉Python从这个类的MRO序列中,跳过自身开始查找父类方法
  • 第二个cls:把查找后的方法绑定到这个类上,调用时自动传入cls作为类方法的第一个参数

运行这段代码后,会正常输出:

init <class '__main__.Bar'> (<class '__main__.Bar'>, <class '__main__.Foo'>, <class 'object'>)
foo

方法2:直接调用父类的类方法

如果你明确只需要调用Foo的foo方法,不想考虑多继承的情况,可以直接写:

class Foo:
    def __init_subclass__(cls):
        print('init', cls, cls.__mro__)
        Foo.foo(cls)  # 直接指定父类调用
    @classmethod
    def foo(cls):
        print('foo')
class Bar(Foo):
    pass

这种写法更直观,但灵活性稍差,适合继承关系简单的场景。

方法3:手动给未绑定super传参(不推荐)

如果你好奇未绑定super怎么用,也可以手动给foo传入cls参数,但这种写法可读性差,一般不建议:

class Foo:
    def __init_subclass__(cls):
        print('init', cls, cls.__mro__)
        super(cls).foo(cls)  # 手动传递cls参数
    @classmethod
    def foo(cls):
        print('foo')
class Bar(Foo):
    pass

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:32:41