Files
PythonLearn/02_python进阶/2_4_推导式与简化写法/README.md

8.5 KiB
Raw Blame History

第 2-4 课:推导式与简化写法

一、本课目标

完成本课后,你将能够:

  1. 解释推导式是什么,以及它适合解决什么问题;
  2. 使用列表推导式转换和筛选数据;
  3. 使用字典推导式创建键值对应关系;
  4. 使用集合推导式收集不重复的数据;
  5. 使用简单的条件表达式返回二选一结果;
  6. 在普通循环和推导式之间选择更清晰的写法;
  7. 避免编写难以阅读的复杂推导式。

二、前置知识

学习本课前,需要掌握:

  • 列表、字典和集合;
  • for 循环和 if 条件判断;
  • 函数、参数和返回值;
  • 字典的 get() 方法。

三、推导式是什么

推导式Comprehension是 Python 根据可遍历数据快速创建新集合的一种写法。

第一阶段中,我们使用普通循环生成新列表:

agent_names = []

for agent in agents:
    agent_names.append(agent["name"])

使用列表推导式可以写成:

agent_names = [agent["name"] for agent in agents]

两段代码的结果相同。推导式没有改变原来的 agents,而是创建并返回一个新列表。

四、列表推导式的基本结构

[需要保存的值 for 临时变量 in 可遍历数据]

示例:

agent_names = [agent["name"] for agent in agents]

建议从右向左理解:

  1. for agent in agents:依次取出每个 Agent
  2. agent["name"]:取得当前 Agent 的名称;
  3. [...]:把每次得到的名称放入新列表。

推导式中的 agent 只是本次遍历使用的临时变量。

五、使用列表推导式筛选数据

普通循环写法:

enabled_names = []

for agent in agents:
    if agent["enabled"]:
        enabled_names.append(agent["name"])

列表推导式写法:

enabled_names = [
    agent["name"]
    for agent in agents
    if agent["enabled"]
]

带筛选条件的结构是:

[需要保存的值 for 临时变量 in 可遍历数据 if 条件]

只有条件为 True 的数据才会进入新列表。

六、转换与筛选的区别

转换表示每条数据都参与,但保存为另一种形式:

name_lengths = [len(agent["name"]) for agent in agents]

筛选表示只有符合条件的数据才保留:

enabled_agents = [agent for agent in agents if agent["enabled"]]

一个推导式也可以同时转换和筛选:

enabled_names = [
    agent["name"]
    for agent in agents
    if agent["enabled"]
]

七、字典推导式

字典推导式Dictionary Comprehension用于创建新字典

tool_counts = {
    agent["name"]: len(agent.get("tools", []))
    for agent in agents
}

基本结构:

{:  for 临时变量 in 可遍历数据}

上述示例的结果类似:

{
    "代码助手": 2,
    "聊天助手": 1,
}

字典的键不能重复。如果多个数据生成同一个键,后生成的值会覆盖之前的值。因此,应先确认选作键的数据具有合适的唯一性。

八、集合推导式

集合推导式Set Comprehension用于创建不包含重复值的集合

models = {agent["model"] for agent in agents}

基本结构:

{需要保存的值 for 临时变量 in 可遍历数据}

集合与字典都使用花括号,但字典推导式包含 键: 值,集合推导式只有一个值。

如果每个 Agent 中还有一个工具列表,可以使用两层 for

unique_tools = {
    tool
    for agent in agents
    for tool in agent.get("tools", [])
}

它等价于:

unique_tools = set()

for agent in agents:
    for tool in agent.get("tools", []):
        unique_tools.add(tool)

本课只练习这一种容易理解的两层结构,不加入更多条件。

九、条件表达式

条件表达式Conditional Expression可以根据一个条件从两个值中选择一个

status_text = "启用" if enabled else "停用"

执行顺序:

  1. 检查 enabled
  2. 条件为 True,得到 "启用"
  3. 条件为 False,得到 "停用"

它等价于:

if enabled:
    status_text = "启用"
else:
    status_text = "停用"

条件表达式适合简单的二选一。如果每个分支需要执行多步操作,应继续使用普通 if...else

十、筛选条件与条件表达式不要混淆

筛选只决定某条数据是否保留:

[agent["name"] for agent in agents if agent["enabled"]]

条件表达式会为每条数据选择一个结果:

[
    "启用" if agent["enabled"] else "停用"
    for agent in agents
]

第一段结果数量可能减少,第二段会为每个 Agent 产生一个状态文字。

十一、什么时候使用普通循环

以下情况优先使用普通循环:

  • 每次遍历需要执行多个步骤;
  • 需要输出中间过程;
  • 包含多层条件判断;
  • 推导式换行后仍难以理解;
  • 需要在循环中提前 breakreturn

代码行数更少不代表代码更好。能够让自己和其他人快速理解的写法才更合适。

十二、完整示例

示例文件:

02_python进阶/2_4_推导式与简化写法/comprehension_example.py

示例会演示:

  1. 普通循环与列表推导式得到相同结果;
  2. 筛选已启用的 Agent 名称;
  3. 创建名称到工具数量的字典;
  4. 收集所有不重复工具;
  5. 使用条件表达式显示 Agent 状态。

十三、运行方法

在项目根目录运行示例:

python .\02_python进阶\2_4_推导式与简化写法\comprehension_example.py

完成练习后运行:

python .\02_python进阶\2_4_推导式与简化写法\practice.py

十四、预期结果

普通循环结果:['代码助手', '测试助手']
列表推导式结果:['代码助手', '测试助手']
工具数量字典:{'代码助手': 2, '聊天助手': 1, '测试助手': 2}
不重复工具:['搜索', '测试', '终端']
Agent 状态:
- 代码助手:启用
- 聊天助手:停用
- 测试助手:启用

集合没有固定顺序。示例使用 sorted() 只是为了让输出顺序稳定,便于核对;集合本身仍然不保证顺序。

十五、常见错误

15.1 忘记最外层括号

列表推导式使用方括号,字典和集合推导式使用花括号。

15.2 把筛选条件写到错误位置

筛选条件写在 for...in... 后面:

[agent["name"] for agent in agents if agent["enabled"]]

15.3 混淆字典和集合推导式

{agent["name"] for agent in agents}

这是集合,因为没有 键: 值。创建字典必须写冒号。

15.4 推导式过于复杂

不要在一个推导式中堆叠多层条件表达式。看不懂时应立即改回普通循环。

15.5 误以为推导式会修改原数据

推导式通常创建新列表、新字典或新集合。除非其中主动修改对象,否则原集合不会因为推导式本身被替换。

十六、课堂练习

打开 practice.py,依次完成:

  1. 创建全部 Agent 名称列表;
  2. 筛选已启用 Agent 的名称;
  3. 创建名称到模型的字典;
  4. 收集不重复工具;
  5. 使用条件表达式返回状态文字;
  6. main() 中保存并输出所有返回结果。

题目已经给出参数、返回值、示例数据和预期结果。请先独立完成。

十七、参考答案

参考答案暂不写入练习文件。你完成后,我会从正确性、可读性和知识掌握情况三个方面验证,并重点检查你是否能够解释推导式,而不只是记住格式。

十八、本课小结

  • 推导式可以根据已有数据创建新集合;
  • 列表推导式使用 []
  • 字典推导式使用 {键: 值}
  • 集合推导式使用 {值}
  • 末尾的 if 用于筛选;
  • 条件表达式用于从两个结果中选择一个;
  • 推导式适合简单逻辑,复杂逻辑应使用普通循环;
  • 清晰比简短更重要。

十九、验收标准

  • 能用普通循环和列表推导式实现相同功能;
  • 能解释列表推导式各部分的执行顺序;
  • 能使用末尾 if 筛选数据;
  • 能创建名称到模型的字典;
  • 能使用集合推导式去重;
  • 能正确使用简单条件表达式;
  • 能区分筛选条件与条件表达式;
  • 所有练习函数通过 return 返回结果;
  • 推导式不会修改原始 Agent 列表;
  • 没有为了简短而编写难以阅读的复杂表达式。