关于super()未传self参数的疑问:super(B)的特性与用途解析
嘿,这个坑我之前也踩过!来一步步给你把这些问题掰明白:
1.
super(B) 创建的super对象包含什么? 当你只给super()传入一个类参数(比如这里的B)时,Python会返回一个未绑定的super对象。这个对象内部保存了两个关键信息:
- 你传入的类
B本身 B的方法解析顺序(MRO)链,也就是B → A → object
但注意,它没有绑定任何具体的实例——简单说就是,它知道B的父类是谁,但不知道要对哪个实例执行方法。
2. 这个super对象和
B有什么关联? 这个super对象完全是和B类绑定的:它的MRO链是从B的直接父类(也就是A)开始往后走的,所有方法调用都会沿着这条链找对应的父类方法。但因为没有绑定实例,它的所有实例方法(比如__init__)都是未绑定状态——调用这类方法时,你必须手动传入一个实例作为第一个参数,否则方法无法正常工作。
3. 为什么这段代码合法?
在Python3中,super()支持仅传入类参数的语法(Python2不行,必须传两个参数),所以解释器不会在语法检查阶段拦着你。而你代码里调用super(B).__init__()时没传self,按道理应该抛出TypeError才对,你说没报错也没输出可能是运行环境的特殊情况?不过不管怎样,语法上这段代码是符合Python规范的,只是运行时行为不符合预期。
4.
super(B) 有没有实际用途? 当然有!虽然平时我们更常用super().__init__()(自动绑定当前实例和类),但未绑定的super对象在一些场景下很有用:
- 类方法中调用父类类方法:如果
B有一个类方法,想调用A的同名类方法,可以用super(B).class_method(cls),因为类方法的第一个参数是cls,刚好可以手动传给未绑定的super方法。 - 手动绑定实例:比如你可以把未绑定的super对象和实例绑定后调用方法,像这样:
sup = super(B); sup.__init__(b),这时候就会正常调用A的__init__并输出'A'。 - 元编程场景:在一些动态操作类的场景中,你需要不依赖实例就访问父类的方法或属性,未绑定的super对象就能帮你做到这一点。
顺带补一句:你的代码里如果改成super().__init__()(不传任何参数,Python3会自动绑定当前实例和类),就能正常输出'A'了,这也是我们平时写子类构造函数的标准写法。
内容的提问来源于stack exchange,提问作者Edvard Fagerholm
相关产品推荐
相关产品推荐

