首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
第 13章 性能测量和大O算法分析
13.1 timeit模块
13.2 cProfile分析器
13.3 大O算法分析
13.4 大O阶
13.4.1 使用书架打比方描述大O阶
13.4.2 大O 测量的是最坏情况
13.5 确定代码的大O 阶
13.5.1 为什么低阶项和系数不重要
13.5.2 大O 分析实例
13.5.3 常见函数调用的大O 阶
13.5.4 一眼看出大O 阶
13.5.5 当n 很小时,大O并不重要,而n通常都很小
第 14章 项目实战
14.1 汉诺塔
14.1.1 汉诺塔输出
14.1.2 汉诺塔源代码
14.1.3 汉诺塔编写代码
14.2 四子棋
14.2.1 四子棋输出
14.2.2 四子棋源代码
14.2.3 四子棋编写代码
第 15章 面向对象编程和类
15.1 拿现实世界打比方:填写表格
15.2 基于类创建对象
15.3 创建一个简单的类——WizCoin
15.3.1 方法__init__()和self
15.3.2 特性
15.3.3 私有特性和私有方法
15.4 函数type()和特性__qualname__
15.5 非OOP 和OOP 的例子:井字棋
15.6 为现实世界设计类是一件难事儿
第 16章 面向对象编程和继承
16.1 继承的原理
16.1.1 重写方法
16.1.2 super()函数
16.1.3 倾向于组合而非继承
16.1.4 继承的缺点
16.2 函数isinstance()和issubclass()
16.3 类方法
16.4 类特性
16.5 静态方法
16.6 何时应该使用类和静态的面向对象特性
16.7 面向对象的行话
16.7.1 封装
16.7.2 多态性
16.8 何时不应该使用继承
16.9 多重继承
16.10 方法解析顺序
第 17章 Python 风格的面向对象编程:属性和魔术方法
17.1 属性
17.1.1 将特性转换为属性
17.1.2 使用setter 验证数据
17.1.3 只读属性
17.1.4 什么时候应该使用属性
17.2 Python 的魔术方法
17.2.1 字符串表示魔术方法
17.2.2 数值魔术方法
17.2.3 反射数值魔术方法
17.2.4 原地魔术方法
17.2.5 比较魔术方法
当前位置:
首页>>
技术小册>>
Python编程轻松进阶(五)
小册名称:Python编程轻松进阶(五)
### 16.1.2 `super()` 函数:深入理解与高效应用 在Python的面向对象编程(OOP)中,`super()` 函数是一个非常重要的特性,它允许子类调用父类(超类)的一个方法。这一机制极大地增强了代码的复用性和灵活性,尤其是在处理多继承时,能够清晰地解决方法解析顺序(Method Resolution Order, MRO)的问题。本章节将深入探讨`super()`函数的工作原理、使用场景、最佳实践以及避免的常见陷阱。 #### 1. `super()` 函数基础 `super()` 函数返回了一个代表父类的临时对象,这个对象允许你调用父类的方法。在Python 3中,`super()` 的使用变得更为简单,通常只需要不带任何参数地调用它(Python 2中需要显式指定类和实例作为参数)。这使得在子类中调用父类的方法变得更加直观和方便。 ##### 示例:基本用法 ```python class Parent: def __init__(self, name): self.name = name print(f"Parent __init__, name: {self.name}") def greet(self): print(f"Hello, I'm {self.name} from Parent") class Child(Parent): def __init__(self, name, age): super().__init__(name) # 调用父类的 __init__ self.age = age print(f"Child __init__, age: {self.age}") def greet(self): super().greet() # 调用父类的 greet print(f"I'm also {self.age} years old.") # 使用 Child 类 child_instance = Child("Alice", 10) child_instance.greet() ``` 输出: ``` Parent __init__, name: Alice Child __init__, age: 10 Hello, I'm Alice from Parent I'm also 10 years old. ``` #### 2. `super()` 与方法解析顺序(MRO) 在Python中,当存在多继承时,`super()` 如何决定调用哪个父类的方法,依赖于Python的MRO机制。MRO决定了类的方法解析顺序,它确保了每个基类被访问一次且仅一次(在继承链中),从而避免了无限递归。 Python 3 使用C3线性化算法来计算MRO,这个算法确保了子类始终优先于它们的父类被访问,并且保持了左到右的声明顺序。 ##### 示例:多继承与MRO ```python class A: def greet(self): print("Hello from A") class B(A): def greet(self): super().greet() print("Hello from B") class C(A): def greet(self): print("Hello from C") class D(B, C): pass # 使用 D 类 d_instance = D() d_instance.greet() ``` 输出: ``` Hello from C Hello from B ``` 这里,`D` 类继承自 `B` 和 `C`,而 `B` 和 `C` 都继承自 `A`。尽管 `B` 在继承声明中先于 `C`,但根据C3线性化算法计算出的MRO是 `D, B, C, A`。因此,当 `D` 类的实例调用 `greet()` 时,首先会找到 `B` 类的 `greet()`,然后通过 `super()` 调用 `C` 类的 `greet()`(因为 `C` 在MRO中紧随 `B` 之后),最后才是 `A` 类的 `greet()`(尽管 `A` 在继承树中更上层)。 #### 3. `super()` 的高级用法 ##### 3.1 在方法中动态调用父类 `super()` 不仅仅用于初始化(`__init__`)或方法重写。它可以在任何需要调用父类方法的地方使用,包括在类的其他方法中。 ##### 3.2 使用 `super()` 调用非直接父类的方法 尽管 `super()` 通常用于调用直接父类的方法,但由于MRO的存在,它实际上可以间接地调用更上层基类中的方法,尤其是在多继承场景中。 ##### 3.3 在复杂继承结构中的应用 在具有复杂继承关系的类中,合理使用 `super()` 可以帮助维护代码的清晰性和可维护性。通过遵循MRO规则,可以确保所有基类的方法都被正确地调用,且不会遗漏。 #### 4. 最佳实践与陷阱 ##### 4.1 总是使用 `super()` 进行初始化 在子类的 `__init__` 方法中,总是应该首先调用父类的 `__init__` 方法,使用 `super()` 是推荐的做法。这有助于确保父类被正确初始化,且子类能够继承父类的所有属性。 ##### 4.2 避免在 `super()` 调用中传递不必要的参数 仅传递父类方法所需的参数给 `super()`,避免传递子类特有的参数,这可能导致错误或混淆。 ##### 4.3 理解MRO对 `super()` 调用的影响 在多继承情况下,理解MRO如何影响 `super()` 的行为至关重要。错误地假设 `super()` 的行为可能会导致难以追踪的错误。 ##### 4.4 谨慎处理 `super()` 在静态方法和类方法中的使用 虽然 `super()` 在实例方法中非常有用,但在静态方法和类方法中它的行为可能不是你所期望的,因为静态方法和类方法不直接关联到类的实例,因此MRO的上下文可能不适用。 #### 5. 结论 `super()` 函数是Python面向对象编程中一个强大的工具,它使得子类能够安全、有效地调用父类的方法,尤其是在处理多继承时。通过深入理解 `super()` 的工作原理和MRO机制,开发者可以编写出更加清晰、可维护的Python代码。在使用 `super()` 时,遵循最佳实践并注意避免常见的陷阱,将有助于提升代码的质量和可靠性。
上一篇:
16.1.1 重写方法
下一篇:
16.1.3 倾向于组合而非继承
该分类下的相关小册推荐:
Python合辑7-集合、列表与元组
Python机器学习基础教程(上)
Python合辑3-字符串用法深度总结
Python自动化办公实战
Python与办公-玩转PPT
Python机器学习实战
剑指Python(磨刀不误砍柴工)
Python数据分析与挖掘实战(下)
Python高性能编程与实战
Python合辑1-Python语言基础
Python高并发编程与实战
Python编程轻松进阶(二)