3.2 继承与多态
引言
小白理解 - 继承是什么?
想象动物世界:
动物(Animal) ← 父类/基类 ├── 狗(Dog) ← 子类,继承自动物 ├── 猫(Cat) ← 子类,继承自动物 └── 鸟(Bird) ← 子类,继承自动物继承的好处:
- 所有动物都能"吃"(eat)、"睡"(sleep)—— 写一次,大家都有
- 狗可以额外"叫"(bark)—— 子类可以有自己的特殊功能
- 猫的"叫"是"喵喵",狗的"叫"是"汪汪"—— 同一个动作,不同表现(多态)
一句话:继承 = 子类复用父类的功能,还能加自己的特色
小白理解 - 多态是什么?
多态 = 同一个动作,不同的表现
python# 所有动物都能"叫",但叫法不同 狗.叫() # → "汪汪!" 猫.叫() # → "喵喵~" 鸟.叫() # → "叽叽!" # 你不用管它是什么动物,调用 .叫() 就行 for 动物 in [狗, 猫, 鸟]: 动物.叫() # 自动调用各自的叫法
继承基础
小白理解 - 看懂继承代码
pythonclass BaseAgent: # ← 父类(基类) def execute(self, task): return "基础执行" class SearchAgent(BaseAgent): # ← 子类,括号里写父类名 def execute(self, task): # ← 重写父类方法 return "搜索执行" # ← 子类的专属实现关键点:
class 子类(父类):—— 括号里写父类名就是继承- 子类自动拥有父类的所有方法和属性
- 子类可以"重写"父类方法,实现自己的版本
python
class BaseAgent:
"""基础 Agent 类"""
def __init__(self, name: str):
self.name = name
def execute(self, task: str) -> str:
"""执行任务(子类重写)"""
return f"{self.name} 执行: {task}"
class SearchAgent(BaseAgent):
"""搜索 Agent"""
def execute(self, task: str) -> str:
"""重写执行方法"""
return f"[搜索] {self.name}: 搜索 '{task}'"
class AnalysisAgent(BaseAgent):
"""分析 Agent"""
def execute(self, task: str) -> str:
return f"[分析] {self.name}: 分析 '{task}'"
# 多态:同一接口,不同实现
agents = [
SearchAgent("搜索助手"),
AnalysisAgent("分析助手")
]
for agent in agents:
print(agent.execute("Python 教程"))运行结果解读:
[搜索] 搜索助手: 搜索 'Python 教程' [分析] 分析助手: 分析 'Python 教程'这就是多态:
- 两个 Agent 都调用
.execute()- 但搜索助手执行"搜索",分析助手执行"分析"
- 调用方不需要知道具体是什么类型的 Agent
实战:Agent 层次结构
小白理解 - ABC 和 abstractmethod
ABC(抽象基类) = 只能被继承,不能直接使用的"模板类"
类比:驾照考试大纲
- 大纲规定:必须会"侧方停车"、"倒车入库"
- 但大纲本身不能开车,只是规定要求
- 学员(子类)必须学会这些技能,才能拿到驾照
pythonfrom abc import ABC, abstractmethod class Agent(ABC): # ← ABC = 抽象基类 @abstractmethod # ← 标记为"必须实现" def process(self, input): # ← 子类必须写这个方法 pass # 错误示范: agent = Agent() # ❌ 报错!抽象类不能实例化 # 正确做法: class MyAgent(Agent): def process(self, input): # ✅ 子类实现了这个方法 return "处理结果" agent = MyAgent() # ✅ 可以创建
小白理解 - super() 是什么?
super()= 调用父类的方法pythonclass LLMAgent(Agent): def __init__(self, name, model): super().__init__(name) # ← 先让父类完成初始化 self.model = model # ← 再添加子类特有的属性类比:你继承了爸爸的房子(
super().__init__()),然后自己装修添家具(self.model)
python
from abc import ABC, abstractmethod
from typing import List
class Agent(ABC):
"""抽象 Agent 基类"""
def __init__(self, name: str):
self.name = name
self.history: List[str] = []
@abstractmethod
def process(self, input: str) -> str:
"""处理输入(子类必须实现)"""
pass
def log(self, message: str) -> None:
"""记录日志"""
self.history.append(f"[{self.name}] {message}")
class LLMAgent(Agent):
"""LLM Agent"""
def __init__(self, name: str, model: str):
super().__init__(name)
self.model = model
def process(self, input: str) -> str:
self.log(f"使用 {self.model} 处理")
return f"LLM 响应: {input}"
class ToolAgent(Agent):
"""工具 Agent"""
def __init__(self, name: str, tools: List[str]):
super().__init__(name)
self.tools = tools
def process(self, input: str) -> str:
self.log(f"使用工具: {self.tools}")
return f"工具执行结果"
# 使用
llm_agent = LLMAgent("GPT助手", "gpt-4")
tool_agent = ToolAgent("工具助手", ["search", "calc"])
print(llm_agent.process("你好"))
print(tool_agent.process("搜索"))代码结构图解:
Agent(抽象基类) │ ├── name ← 所有Agent都有名字 ├── history ← 所有Agent都有历史记录 ├── log() ← 所有Agent都能记日志 └── process() ← 抽象方法,子类必须实现 │ ├── LLMAgent.process() → 调用 LLM 处理 └── ToolAgent.process() → 调用工具处理
本节小结
| 概念 | 一句话解释 | 记忆口诀 |
|---|---|---|
| 继承 | 子类复用父类的功能 | 继承 = 遗产 |
| 多态 | 同一接口,不同实现 | 多态 = 变形 |
| 重写 | 子类替换父类的方法 | 重写 = 改造 |
| super() | 调用父类的方法 | super = 爸爸 |
| ABC | 只能继承不能实例化的类 | ABC = 模板 |
| @abstractmethod | 标记子类必须实现的方法 | abstract = 必做题 |