super函数

本文详细解析了Python中super函数的工作原理,特别是如何解决多继承问题,如钻石继承。通过实例解释了super函数如何根据MRO(方法解析顺序)来调用父类的方法。

super函数主要用来解决多继承,多继承就是一个子类继承多个父类。比如狗即继承哺乳类,又继承宠物类,如果再继承一个动物类,组成层级就是钻石继承啦,super主要是用来解决钻石继承,和c++用虚拟函数不同,它用一个叫mro的概念

>>> Leaf.mro()

[<class '__main__.Leaf'>, <class '__main__.Medium1'>, <class '__main__.Medium2'>, <class '__main__.Base'>, <type 'object'>]
[具体说明](https://www.cnblogs.com/testview/p/4651198.html)

super(Leaf, self).init()的意思是说:

获取self所属类的mro, 也就是[Leaf, Medium1, Medium2, Base]
从mro中Leaf右边的一个类开始,依次寻找__init__函数。这里是从Medium1开始寻找
一旦找到,就把找到的__init__函数绑定到self对象,并返回

### Super 函数的用法与原理 #### 1. **Super 函数的基本功能** `super()` 是 Python 提供的一个内置函数,主要作用是用来调用父类的方法。它的核心目的是解决多重继承时方法查找顺序的问题,并提供了一种优雅的方式来访问父类中的方法[^2]。 在单继承情况下,虽然可以直接通过 `ParentClass.method(self, ...)` 的方式来显式调用父类方法,但这并不是最佳实践。因为如果将来需要更改继承关系(比如将父类替换为另一个类),则需要手动更新所有硬编码的地方。而使用 `super()` 可以使代码更具灵活性和可维护性[^3]。 --- #### 2. **Super 函数的工作机制** `super()` 的工作基于 MRO (Method Resolution Order),即方法解析顺序。当在一个类中调用 `super()` 时,实际上会返回一个代理对象,这个代理对象指向当前类之后的第一个父类及其后续的 MRO 列表[^1]。 以下是具体的流程: - 当前类以及其实例作为参数传递给 `super()`。 - 返回的对象会在 MRO 列表中继续向下寻找合适的目标方法。 - 找到目标方法后执行之。 例如下面的例子展示了如何利用 `super()` 调用父类初始化方法: ```python class Parent: def __init__(self, name): self.name = name print(f"Parent init called with {name}") class Child(Parent): def __init__(self, name, age): super().__init__(name) # 调用父类的构造函数 self.age = age print(f"Child init called with {age}") child_instance = Child('Alice', 10) ``` 在这个例子中,当我们创建 `Child` 类的新实例时,不仅设置了自身的属性 `age`,还借助 `super()` 自动完成了对父类 `Parent` 初始化逻辑的调用。 --- #### 3. **Super 在多重继承下的表现** 考虑如下复杂情况: ```python class Base1: def greet(self): print("Hello from Base1") class Base2: def greet(self): print("Hi there! From Base2") class Derived(Base1, Base2): def greet(self): super().greet() derived_obj = Derived() derived_obj.greet() # 输出什么? ``` 这里的关键在于理解 `Derived` 的 MRO 序列是什么样的。对于上述代码片段来说,`Derived.__mro__` 结果将是 `(Derived, Base1, Base2, object)`。所以当我们在 `Derived.greet()` 方法内部调用了 `super().greet()` 后,实际上是沿着这条链路找到第一个实现了 `greet` 方法的类 —— 即 `Base1`。 因此最终输出应为 `"Hello from Base1"`。 需要注意的是,即使交换了基类声明位置变成 `class Derived(Base2, Base1):...` ,那么新的 MRO 将变为 `(Derived, Base2, Base1, object)`,从而导致不同的行为结果:"Hi there! From Base2"[^3]。 --- #### 4. **无参 vs 带参形式的区别** 除了最常见的零参数写法外,`super(type[, instance])` 支持带两个参数的形式。这允许更灵活地指定上下文中使用的类型及关联实例/子类。不过通常推荐采用简洁版语法除非确实遇到特殊需求才需回退至完整签名模式下操作[^1]。 简单对比两者差异如下所示: | 特性 | 零参数形式 | 完整两参数形式 | |-------------------|----------------------------|---------------------------| | 场景适用范围 | 默认适用于当前所在类 | 明确指定了参与运算的具体类别 | | 是否依赖隐式的 self 参数 | Yes | No | 典型应用场景可能包括单元测试框架设计等领域当中需要用到动态切换不同层次间相互协作的情形之下更为常见一些[^2]。 --- ### 总结 综上所述,`super()` 不仅简化了传统意义上繁琐的手工管理父类引用过程,更重要的是它能够很好地配合 Python 多重继承体系结构一起发挥作用,使得程序具备更强健的生命力与适应能力面对未来可能出现的变化挑战! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值