第11章 继承与多态
学习目标
完成本章学习后,读者将能够:
- 理解Python继承机制与MRO(方法解析顺序)的工作原理
- 运用super()正确调用父类方法,理解协作式多继承
- 掌握Mixin模式实现代码复用的最佳实践
- 理解多态与鸭子类型的设计哲学
- 使用ABC和Protocol定义抽象接口与结构化类型
11.1 继承基础
11.1.1 单继承
class Animal:
def __init__(self, name: str):
self.name = name
def speak(self) -> str:
raise NotImplementedError("子类必须实现speak方法")
def info(self) -> str:
return f"I am {self.name}"
class Dog(Animal):
def speak(self) -> str:
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self) -> str:
return f"{self.name} says Meow!"
dog = Dog("Buddy")
print(dog.speak()) # "Buddy says Woof!"
print(isinstance(dog, Animal)) # True
print(issubclass(Dog, Animal)) # True11.1.2 super()与协作式调用
class Animal:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
class Dog(Animal):
def __init__(self, name: str, age: int, breed: str):
super().__init__(name, age) # 调用父类初始化
self.breed = breed
def info(self) -> str:
return f"{self.name}, {self.age}yo, {self.breed}"学术注记:
super()并非简单调用"父类方法",而是按照MRO顺序调用下一个类的方法。这使得多继承中的协作式调用成为可能。Python 3中super()无需参数,等价于super(__class__, self)。
11.1.3 方法重写与扩展
class Shape:
def __init__(self, color: str):
self.color = color
def area(self) -> float:
raise NotImplementedError
def describe(self) -> str:
return f"{self.color} shape, area={self.area():.2f}"
class Rectangle(Shape):
def __init__(self, color: str, width: float, height: float):
super().__init__(color)
self.width = width
self.height = height
def area(self) -> float:
return self.width * self.height
class Circle(Shape):
def __init__(self, color: str, radius: float):
super().__init__(color)
self.radius = radius
def area(self) -> float:
import math
return math.pi * self.radius ** 2
shapes: list[Shape] = [Rectangle("red", 5, 3), Circle("blue", 4)]
for s in shapes:
print(s.describe())11.2 多继承与MRO
11.2.1 多继承
class Flyable:
def fly(self) -> str:
return "Flying!"
class Swimmable:
def swim(self) -> str:
return "Swimming!"
class Duck(Flyable, Swimmable):
def quack(self) -> str:
return "Quack!"
duck = Duck()
print(duck.fly()) # "Flying!"
print(duck.swim()) # "Swimming!"11.2.2 MRO(方法解析顺序)
class A:
def method(self):
print("A")
class B(A):
def method(self):
print("B")
super().method()
class C(A):
def method(self):
print("C")
super().method()
class D(B, C):
def method(self):
print("D")
super().method()
d = D()
d.method() # D → B → C → A
print(D.__mro__) # (D, B, C, A, object)学术注记:Python使用C3线性化算法计算MRO,保证:1)子类先于父类;2)按声明顺序遍历;3)对每个类只访问一次。菱形继承中,MRO确保
super()链不会重复调用任何类。
11.2.3 Mixin模式
class LogMixin:
def log(self, message: str) -> None:
print(f"[LOG] {self.__class__.__name__}: {message}")
class SerializableMixin:
def to_dict(self) -> dict:
return self.__dict__.copy()
class TimestampMixin:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
from datetime import datetime
self.created_at = datetime.now()
class Article(TimestampMixin, LogMixin, SerializableMixin):
def __init__(self, title: str, content: str):
super().__init__(title=title, content=content)
self.title = title
self.content = content
article = Article("Python", "Python is awesome!")
article.log("Article created")
print(article.to_dict())工程实践:Mixin类应遵循以下原则:1)不单独使用,仅用于多继承混入;2)不定义
__init__(或使用super().__init__协作);3)命名以Mixin结尾;4)保持单一职责。
11.3 多态
11.3.1 多态与鸭子类型
class Dog:
def speak(self) -> str:
return "Woof!"
class Cat:
def speak(self) -> str:
return "Meow!"
class Robot:
def speak(self) -> str:
return "Beep!"
def make_them_speak(speakers: list) -> None:
for s in speakers:
print(s.speak()) # 鸭子类型:只要有speak方法即可
make_them_speak([Dog(), Cat(), Robot()])学术注记:Python的多态基于鸭子类型——"如果它走起来像鸭子、叫起来像鸭子,那它就是鸭子"。与Java的静态多态(基于接口/继承)不同,Python不要求对象显式声明类型,只需实现所需方法即可。这是Python灵活性的核心来源。
11.3.2 协议式多态
# Python内置协议示例
class Story:
def __init__(self, title: str, content: str):
self.title = title
self.content = content
def __len__(self) -> int: # len协议
return len(self.content)
def __getitem__(self, index): # 迭代协议
return self.content[index]
story = Story("Hello", "Once upon a time...")
print(len(story)) # 20
for char in story[:5]: # 支持迭代和切片
print(char)11.4 抽象类与接口
11.4.1 ABC(抽象基类)
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self) -> float:
pass
@abstractmethod
def perimeter(self) -> float:
pass
def describe(self) -> str:
return f"Area: {self.area():.2f}, Perimeter: {self.perimeter():.2f}"
# Shape() # TypeError: 无法实例化抽象类
class Rectangle(Shape):
def __init__(self, width: float, height: float):
self.width = width
self.height = height
def area(self) -> float:
return self.width * self.height
def perimeter(self) -> float:
return 2 * (self.width + self.height)
rect = Rectangle(5, 3)
print(rect.describe())11.4.2 Protocol(结构化类型)
from typing import Protocol
class Drawable(Protocol):
def draw(self) -> None: ...
class Circle:
def __init__(self, radius: float):
self.radius = radius
def draw(self) -> None:
print(f"Drawing circle (r={self.radius})")
class Square:
def __init__(self, side: float):
self.side = side
def draw(self) -> None:
print(f"Drawing square (side={self.side})")
def render(shape: Drawable) -> None:
shape.draw() # 任何有draw()方法的对象都符合
render(Circle(5)) # 无需继承Drawable
render(Square(4)) # 结构化类型检查学术注记:Protocol是结构化类型(Structural Typing)的实现——类型兼容性基于结构(方法签名)而非名义(继承关系)。这与ABC的名义类型(Nominal Typing)形成对比。Protocol更符合Python的鸭子类型哲学,同时提供静态类型检查支持。
11.4.3 ABC vs Protocol对比
| 特性 | ABC | Protocol |
|---|---|---|
| 类型检查 | 名义类型 | 结构化类型 |
| 运行时检查 | isinstance() | @runtime_checkable |
| 继承要求 | 必须显式继承 | 不需要 |
| 静态检查支持 | 是 | 是(mypy) |
| 适用场景 | 框架/库的强制约束 | 接口协议定义 |
11.5 设计模式实践
11.5.1 策略模式
from abc import ABC, abstractmethod
from typing import List
class SortStrategy(ABC):
@abstractmethod
def sort(self, data: List[int]) -> List[int]:
pass
class BubbleSort(SortStrategy):
def sort(self, data: List[int]) -> List[int]:
result = data.copy()
n = len(result)
for i in range(n):
for j in range(0, n - i - 1):
if result[j] > result[j + 1]:
result[j], result[j + 1] = result[j + 1], result[j]
return result
class QuickSort(SortStrategy):
def sort(self, data: List[int]) -> List[int]:
if len(data) <= 1:
return data
pivot = data[len(data) // 2]
left = [x for x in data if x < pivot]
middle = [x for x in data if x == pivot]
right = [x for x in data if x > pivot]
return self.sort(left) + middle + self.sort(right)
class Sorter:
def __init__(self, strategy: SortStrategy):
self._strategy = strategy
def set_strategy(self, strategy: SortStrategy) -> None:
self._strategy = strategy
def sort(self, data: List[int]) -> List[int]:
return self._strategy.sort(data)
sorter = Sorter(BubbleSort())
print(sorter.sort([3, 1, 4, 1, 5, 9, 2, 6]))
sorter.set_strategy(QuickSort())
print(sorter.sort([3, 1, 4, 1, 5, 9, 2, 6]))11.5.2 模板方法模式
from abc import ABC, abstractmethod
class DataProcessor(ABC):
def process(self, data: str) -> str:
data = self.read(data)
data = self.validate(data)
data = self.transform(data)
data = self.save(data)
return data
def read(self, data: str) -> str:
print(f"读取数据: {data}")
return data
@abstractmethod
def validate(self, data: str) -> str:
pass
@abstractmethod
def transform(self, data: str) -> str:
pass
def save(self, data: str) -> str:
print(f"保存数据: {data}")
return data
class JsonProcessor(DataProcessor):
def validate(self, data: str) -> str:
import json
json.loads(data)
print("JSON验证通过")
return data
def transform(self, data: str) -> str:
import json
obj = json.loads(data)
obj["processed"] = True
return json.dumps(obj)
class XmlProcessor(DataProcessor):
def validate(self, data: str) -> str:
print("XML验证通过")
return data
def transform(self, data: str) -> str:
return data.upper()
json_processor = JsonProcessor()
json_processor.process('{"name": "test"}')11.5.3 工厂模式
from abc import ABC, abstractmethod
from typing import Type
class Animal(ABC):
@abstractmethod
def speak(self) -> str:
pass
class Dog(Animal):
def speak(self) -> str:
return "Woof!"
class Cat(Animal):
def speak(self) -> str:
return "Meow!"
class AnimalFactory:
_registry: dict[str, Type[Animal]] = {}
@classmethod
def register(cls, name: str) -> callable:
def decorator(animal_class: Type[Animal]) -> Type[Animal]:
cls._registry[name] = animal_class
return animal_class
return decorator
@classmethod
def create(cls, name: str) -> Animal:
if name not in cls._registry:
raise ValueError(f"Unknown animal: {name}")
return cls._registry[name]()
@AnimalFactory.register("dog")
class RegisteredDog(Animal):
def speak(self) -> str:
return "Registered Woof!"
dog = AnimalFactory.create("dog")
print(dog.speak())11.5.4 组合模式
from abc import ABC, abstractmethod
from typing import List
class Component(ABC):
@abstractmethod
def operation(self) -> str:
pass
class Leaf(Component):
def __init__(self, name: str):
self.name = name
def operation(self) -> str:
return self.name
class Composite(Component):
def __init__(self, name: str):
self.name = name
self._children: List[Component] = []
def add(self, component: Component) -> None:
self._children.append(component)
def remove(self, component: Component) -> None:
self._children.remove(component)
def operation(self) -> str:
results = [child.operation() for child in self._children]
return f"{self.name}({', '.join(results)})"
root = Composite("root")
root.add(Leaf("A"))
branch = Composite("branch")
branch.add(Leaf("B"))
branch.add(Leaf("C"))
root.add(branch)
print(root.operation())11.6 前沿技术动态
11.6.1 结构化子类型(PEP 544)
from typing import Protocol, runtime_checkable
@runtime_checkable
class Drawable(Protocol):
def draw(self) -> None: ...
def render(obj: Drawable) -> None:
obj.draw()
class Circle:
def draw(self) -> None:
print("Drawing circle")
render(Circle())11.6.2 类型系统增强
from typing import Self, TypeVar, Generic
T = TypeVar('T')
class Container(Generic[T]):
def __init__(self, value: T):
self.value = value
def map(self, f: callable[[T], T]) -> Self:
return type(self)(f(self.value))11.6.3 组合优于继承
from dataclasses import dataclass
@dataclass
class FlyBehavior:
def fly(self) -> str:
return "Flying"
@dataclass
class QuackBehavior:
def quack(self) -> str:
return "Quacking"
class Duck:
def __init__(self):
self.fly_behavior = FlyBehavior()
self.quack_behavior = QuackBehavior()11.6.4 模式匹配与多态
from dataclasses import dataclass
@dataclass
class Success:
value: int
@dataclass
class Failure:
error: str
def handle_result(result: Success | Failure) -> str:
match result:
case Success(value=v):
return f"Success: {v}"
case Failure(error=e):
return f"Error: {e}"11.7 本章小结
本章系统介绍了Python继承与多态的完整体系:
- 继承:单继承、super()协作调用、方法重写与扩展
- 多继承:MRO(C3线性化)、Mixin模式最佳实践
- 多态:鸭子类型、协议式多态、灵活的消息传递
- 抽象:ABC强制约束、Protocol结构化类型
- 设计模式:策略模式、模板方法、工厂模式、组合模式
11.7.1 继承设计原则
| 原则 | 说明 | 建议 |
|---|---|---|
| 组合优于继承 | 继承是强耦合 | 优先使用has-a关系 |
| 里氏替换原则 | 子类可替换父类 | 子类不应违反父类契约 |
| 接口隔离 | 接口要小而专 | 多个小接口优于一个大接口 |
| 依赖倒置 | 依赖抽象而非具体 | 面向接口编程 |
| 单一职责 | 类只有一个变化原因 | 避免上帝类 |
11.7.2 常见陷阱与规避
# 陷阱1:继承层次过深
class A: pass
class B(A): pass
class C(B): pass
class D(C): pass # 难以维护!
# 正确做法:使用组合
class Component:
def operation(self): pass
class Object:
def __init__(self, component: Component):
self.component = component
# 陷阱2:滥用多继承
class A:
def method(self): print("A")
class B(A):
def method(self): print("B")
class C(A):
def method(self): print("C")
class D(B, C): # MRO复杂
pass
# 正确做法:使用Mixin
class LogMixin:
def log(self): pass
class ValidMixin:
def validate(self): pass
class MyClass(LogMixin, ValidMixin):
pass
# 陷阱3:忘记调用super().__init__()
class Parent:
def __init__(self, value):
self.value = value
class Child(Parent):
def __init__(self, value, extra):
# 忘记super().__init__(value)
self.extra = extra
# 正确做法
class Child(Parent):
def __init__(self, value, extra):
super().__init__(value)
self.extra = extra11.8 练习题
基础题
创建Vehicle基类,派生Car和Bicycle类,各自实现移动方式描述。
使用多态实现图形面积计算器,支持矩形、圆形和三角形。
创建抽象类Shape,要求子类实现area()和perimeter()。
进阶题
实现LogMixin和TimestampMixin,为任意类添加日志和时间戳功能。
使用Protocol定义Iterator接口,并实现自定义迭代器。
实现一个简单的插件系统,使用ABC定义插件接口,支持动态加载。
项目实践
- 图形编辑器框架:编写一个程序,要求:
- 使用ABC定义Shape接口(area、perimeter、draw、resize)
- 实现Rectangle、Circle、Triangle具体图形
- 使用Mixin添加Serializable和Comparable功能
- 使用Protocol定义Renderer接口
- 支持Canvas类管理多个图形,计算总面积
- 实现图形的序列化与反序列化
思考题
Python的MRO为什么使用C3线性化?菱形继承中super()是如何工作的?
Mixin模式与普通多继承有什么区别?什么情况下应使用Mixin?
Protocol相比ABC有什么优势?在什么场景下应优先使用Protocol?
11.9 延伸阅读
11.9.1 面向对象设计
- 《设计模式:可复用面向对象软件的基础》 (GoF) — 23种经典设计模式
- 《Head First设计模式》 — 设计模式入门经典
- 《敏捷软件开发:原则、模式与实践》 (Robert C. Martin) — OOP实践指南
- SOLID原则详解 — 面向对象设计的五大原则
11.9.2 Python继承机制
- PEP 3135 — New Super (https://peps.python.org/pep-3135/) — Python 3 super()语法
- Python MRO文档 (https://www.python.org/download/releases/2.3/mro/) — C3线性化算法
- 《Fluent Python》第12-14章 — 继承与多态深度解析
11.9.3 类型系统
- PEP 544 — Protocols (https://peps.python.org/pep-0544/) — 结构化子类型
- PEP 3119 — Abstract Base Classes (https://peps.python.org/pep-3119/) — ABC规范
- mypy Protocol文档 (https://mypy.readthedocs.io/en/stable/protocols.html) — 静态类型检查
11.9.4 设计模式资源
- Refactoring Guru (https://refactoring.guru/design-patterns) — 设计模式可视化教程
- Python Patterns (https://github.com/faif/python-patterns) — Python设计模式集合
- 《Python设计模式》 (Dusty Phillips) — Python设计模式实践
下一章:第12章 高级面向对象特性