在__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
相关产品推荐
相关产品推荐

