教程建议 35 分钟学习等级 3/8

PYTHON LESSON 039

一行代码的魔法

掌握列表解析的写法,会用 zip 和 enumerate 优雅地遍历数据。

00 · 学习目标

这一课要解决什么?

先想一想生成 1 到 100 的平方数列表,真的只要一行代码?
完成任务数据加工厂
学习顺序定义 → 语法 → 最小实例 → 独立练习

学完后,你应该能够

  • [表达式 for x in range(...)] 列表解析
  • [x for x in ... if 条件] 带筛选的解析
  • zip 配对遍历、enumerate 带序号遍历

01 · 核心概念

列表解析、zip 与 enumerate

列表解析、zip 与 enumerate:以前生成平方列表要写三行:建空列表、循环、append。列表解析把这三件事压缩进一对方括号:[n * n for n in range(1, 11)]——“对每个 n,算出 n*n,装成列表”。

考级对应GESP Python 3 级 · 列表解析GESP Python 3 级 · 常用内置函数
学习边界

流程图是算法的表示方法,不是 Python 语法。

02 · 语法与规则

先记住这 3 条,再开始写程序

01[表达式 for x in range(...)] 列表解析

先准确读出这条写法的结构与作用。

02[x for x in ... if 条件] 带筛选的解析

换一组最小数据,手工推演一次结果。

03zip 配对遍历、enumerate 带序号遍历

再用边界值或反例确认它的适用条件。

03 · 完整实例

代码、运行结果和解释放在一起看

list-comprehension-magic.pyPYTHON 3.12
# 一行代码的魔法:列表解析、zip 与 enumerate
squares = [n * n for n in range(1, 11)]
print("1 到 10 的平方:", squares)

evens = [n for n in range(1, 21) if n % 2 == 0]
print("20 以内的偶数:", evens)

names = ["小明", "小红", "小刚"]
scores = [88, 95, 79]
for name, score in zip(names, scores):
    print(name, "考了", score, "分")

for i, name in enumerate(names):
    print("学号", i + 1, "号:", name)
运行结果OUTPUT
1 到 10 的平方: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
20 以内的偶数: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
小明 考了 88 分
小红 考了 95 分
小刚 考了 79 分
学号 1 号: 小明
学号 2 号: 小红
学号 3 号: 小刚

列表解析 = 把“循环 + append”压缩成一行,读熟了反而更清晰。

在新标签运行和修改这个实例已装入本课代码 · 可自定义输入 · 可提交判题

04 · 逐步理解

每一步只解决一个问题

  1. 01

    从三行到一行

    以前生成平方列表要写三行:建空列表、循环、append。列表解析把这三件事压缩进一对方括号:[n * n for n in range(1, 11)]——“对每个 n,算出 n*n,装成列表”。

    PYTHON
    squares = [n * n for n in range(1, 11)]
  2. 02

    加上筛选条件

    方括号尾巴上接一个 if,就只有满足条件的元素能入选:[n for n in range(1, 21) if n % 2 == 0] 挑出所有偶数。循环、加工、筛选,全在一行里。

    PYTHON
    evens = [n for n in range(1, 21) if n % 2 == 0]
  3. 03

    zip:两条列表手拉手

    zip(names, scores) 把两个列表按位置配对:(小明,88)、(小红,95)……循环时一次解包出两个值,再也不用手动数下标。配对长度不同时,以短的为准。

    PYTHON
    for name, score in zip(names, scores):
        print(name, score)
  4. 04

    enumerate:自带号码牌

    enumerate(names) 遍历时同时给出序号和值:i 从 0 开始,name 逐个取出。想要学号从 1 开始?用 i + 1,或者 enumerate(names, 1)。

    PYTHON
    for i, name in enumerate(names):
        print(i + 1, name)
  5. 05

    组合拳:zip + 列表解析

    两行成绩求每个人的总分:[a + b for a, b in zip(chinese, math)]——zip 负责配对,解析负责计算,一行搞定。这就是三级考试想看到的“优雅代码”。

    PYTHON
    totals = [a + b for a, b in zip([80, 90], [75, 95])]
    print(totals)
  6. 06

    什么时候不用解析

    列表解析适合“生成新列表”;如果循环里要做打印、判断分支等复杂操作,老老实实写普通 for 更清楚。魔法要用在合适的地方,可读性永远排第一。

05 · 练习与检验

自己写出来,才算真正学会

本课实作步骤
  1. 1运行程序,感受一行代码的威力
  2. 2用列表解析生成 1 到 20 的立方数
  3. 3给解析加上“只要偶数”的条件
  4. 4用 zip 配对你和同桌的语文数学成绩
打开本课编程实验室编辑、运行、测试、判题都在一个页面完成

06 · 完整知识

继续理解定义、规则和适用边界

第一次学习先完成上面的六个步骤;需要查定义、核对规则、分析误区或理解“为什么”时,再展开对应知识章。

Python 基础条件、循环与程序流程准确理解 if、for、while、range、break、continue 和循环嵌套,而不是背代码模板。

正式定义

控制流决定下一条要执行的语句。分支依据布尔条件选择路径;循环在满足规则时重复执行代码块。Python 用冒号和缩进界定代码块。

必须掌握

  • if/elif/else 从上到下判断,只执行第一个为真的分支;else 不写条件。
  • for 依次取得可迭代对象中的元素;range(start, stop, step) 包含 start、不包含 stop,step 不能为 0。
  • while 在每轮开始前检查条件;循环体必须让状态向终止条件推进。
  • break 结束最内层循环,continue 跳过本轮剩余语句,循环的 else 仅在没有被 break 终止时执行。
  • 嵌套循环的总执行次数通常需要把各层次数相乘;内层 break 不会结束外层循环。
  • 边界测试至少覆盖空范围、单个元素、第一项命中、最后一项命中和始终不命中。

常见误区

  • range 的右端点多算或少算一次
  • while 忘记更新状态造成死循环
  • 把两个互斥条件写成两个独立 if
  • 误以为 break 会跳出所有嵌套循环

适用边界

  • 流程图是算法的表示方法,不是 Python 语法。
  • 递归也能表达重复,但有调用开销和递归深度限制,不能无条件代替循环。
打开本章完整示例与独立阅读页 →
核心数据结构列表、元组、字典与集合按顺序、可变性、唯一性和查找需求选择容器,并掌握遍历、推导式、排序与复制。

正式定义

容器保存多个对象。list 是可变有序序列,tuple 是不可变有序序列,dict 保存唯一键到值的映射,set 保存无序且不重复的可哈希对象。

必须掌握

  • list 支持下标、切片、append、extend、insert、pop、remove 与 sort;多数修改方法返回 None。
  • tuple 的逗号比括号更关键,单元素元组必须写成 (value,)。
  • dict 保持插入顺序;键必须可哈希且唯一,get 可提供缺省值,items 同时遍历键和值。
  • set 用于去重与集合运算:| 并、& 交、- 差、^ 对称差;空集合必须写 set()。
  • enumerate 同时给出序号和值,zip 并行遍历多个可迭代对象,默认在最短输入处停止。
  • 浅复制只复制最外层容器;嵌套可变对象仍可能共享。

常见误区

  • 把 list.sort() 的返回值赋回列表
  • 遍历 dict 时同时改变其大小
  • 用可变 list 当字典键
  • 把 set 当成有固定顺序的序列

适用边界

  • 大量从队首删除时 list.pop(0) 是 O(n),应使用 collections.deque。
  • 需要有序映射的特殊操作、计数或默认值时可查阅 collections,但先理解基本 dict。
打开本章完整示例与独立阅读页 →
Python 基础运算符、表达式与优先级完整区分算术、比较、逻辑、成员、身份和位运算,并用优先级表消除歧义。

正式定义

表达式求值得到一个值。运算符规定如何组合操作数;当一个表达式含多个运算符时,优先级和结合方向决定求值顺序,括号可以明确改变顺序。

必须掌握

  • / 总是得到浮点结果;// 是向负无穷方向取整的整除;% 与 // 满足 a == (a // b) * b + a % b。
  • 比较可以链式书写,如 0 <= x < 10;and/or 会短路并返回最后求值的操作数,不一定返回 bool。
  • == 比较值是否相等,is 比较是否为同一个对象;判断 None 应写 is None。
  • in/not in 做成员测试;对 dict 测试的是键。
  • 位运算作用于整数的二进制位;负整数按无限长二进制补码语义理解。
  • 复杂表达式即使能靠优先级正确运行,也应使用括号表达意图。

常见误区

  • 把 // 当成简单截断
  • 用 is 比较数字或字符串的值
  • 忘记 and 的优先级高于 or
  • 连续位移、比较和逻辑运算却不加括号

适用边界

  • 浮点数比较受二进制表示误差影响,需要按问题选择容差。
  • 运算符可由自定义类重载,因此相同符号对不同类型可能有不同语义。
打开本章完整示例与独立阅读页 →
程序组织模块、导入与常用标准库正确导入模块,并按用途查找 math、random、statistics、collections、heapq、bisect 等标准工具。

正式定义

模块是可导入的 Python 代码单元,包把模块组织成层次。import 先加载模块并创建模块对象,再把名字绑定到当前命名空间;标准库随 Python 分发,不等于第三方包。

必须掌握

  • import module 保留清晰命名空间;from module import name 只导入指定名字;避免 from module import *。
  • math 提供 sqrt、floor、ceil、gcd、log、sin 等数学函数和 pi、e 等常量。
  • random 用于伪随机模拟,不适合密码安全;需要安全随机时使用 secrets。
  • collections.deque 适合双端队列,Counter 适合计数,defaultdict 可按工厂创建缺省值。
  • heapq 实现最小堆,bisect 在已排序序列中二分定位,itertools 提供高效迭代组合工具。
  • if __name__ == '__main__': 用来区分文件被直接运行还是被导入。

常见误区

  • 文件名写成 math.py 导致遮蔽标准库
  • import * 污染命名空间
  • 把 random 当成加密随机数
  • 没有理解工具的数据复杂度就盲目调用

适用边界

  • 标准库非常大,本章覆盖课程会实际依赖的入口;具体函数签名应结合本站条目与运行时帮助查询。
  • Turtle 需要图形窗口,本站文本判题环境不伪造其画布。
打开本章完整示例与独立阅读页 →

完成检查

确认自己会解释、会编写、会验证