第11章 继承与多态 学习目标 完成本章学习后,读者将能够:
理解Python继承机制与MRO(方法解析顺序)的工作原理 运用super()正确调用父类方法,理解协作式多继承 掌握Mixin模式实现代码复用的最佳实践 理解多态与鸭子类型的设计哲学 使用ABC和Protocol定义抽象接口与结构化类型 11.1 继承基础 11.1.1 单继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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()) print (isinstance (dog, Animal)) print (issubclass (Dog, Animal))
11.1.2 super()与协作式调用 1 2 3 4 5 6 7 8 9 10 11 12 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 方法重写与扩展 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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():.2 f} " 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 多继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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()) print (duck.swim())
11.2.2 MRO(方法解析顺序) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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() print (D.__mro__)
学术注记 :Python使用C3线性化算法计算MRO,保证:1)子类先于父类;2)按声明顺序遍历;3)对每个类只访问一次。菱形继承中,MRO确保super()链不会重复调用任何类。
11.2.3 Mixin模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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 多态与鸭子类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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()) make_them_speak([Dog(), Cat(), Robot()])
学术注记 :Python的多态基于鸭子类型 ——“如果它走起来像鸭子、叫起来像鸭子,那它就是鸭子”。与Java的静态多态(基于接口/继承)不同,Python不要求对象显式声明类型,只需实现所需方法即可。这是Python灵活性的核心来源。
11.3.2 协议式多态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Story : def __init__ (self, title: str , content: str ): self .title = title self .content = content def __len__ (self ) -> int : return len (self .content) def __getitem__ (self, index ): return self .content[index] story = Story("Hello" , "Once upon a time..." ) print (len (story)) for char in story[:5 ]: print (char)
11.4 抽象类与接口 11.4.1 ABC(抽象基类) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 from abc import ABC, abstractmethodclass Shape (ABC ): @abstractmethod def area (self ) -> float : pass @abstractmethod def perimeter (self ) -> float : pass def describe (self ) -> str : return f"Area: {self.area():.2 f} , Perimeter: {self.perimeter():.2 f} " 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(结构化类型) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from typing import Protocolclass 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() render(Circle(5 )) 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 策略模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 from abc import ABC, abstractmethodfrom 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 模板方法模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 from abc import ABC, abstractmethodclass 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 工厂模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 from abc import ABC, abstractmethodfrom 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 组合模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 from abc import ABC, abstractmethodfrom 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) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 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 类型系统增强 1 2 3 4 5 6 7 8 9 10 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 组合优于继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 模式匹配与多态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 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 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): pass class LogMixin : def log (self ): pass class ValidMixin : def validate (self ): pass class MyClass (LogMixin, ValidMixin): pass class Parent : def __init__ (self, value ): self .value = value class Child (Parent ): def __init__ (self, value, extra ): self .extra = extra class Child (Parent ): def __init__ (self, value, extra ): super ().__init__(value) self .extra = extra
11.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继承机制 11.9.3 类型系统 11.9.4 设计模式资源 下一章:第12章 高级面向对象特性