循环
引入| English | 释义 | 拼音 |
|---|---|---|
| iteration/ˌɪtəˈreɪʃn/ | 循环 | xún huán |
| infinite loop/ˈɪnfɪnət luːp/ | 死循环 | sǐ xún huán |
| trace table/treɪs ˈteɪbl/ | 跟踪表 | gēn zōng biǎo |
£1000 什么时候变成 £2000?
- 你以每年 5% 的利率存 £1000。要多少年才会超过 £2000?你可以手工一遍又一遍地乘以 1.05,但计算机眨眼就能完成。
- 一遍又一遍地做同一步就是循环(iteration)。这节课讲怎样写出运行正确次数、然后停下来的循环。
balance, years = 1000.0, 0
while balance < 2000.0:
balance *= 1.05
years += 1
print(years, round(balance, 2)) # 15 2078.93
for:次数已知的循环
for i in range(1, 6):对每个值运行一次代码块:1, 2, 3, 4, 5。结束值6不包括在内。range(5)给出0, 1, 2, 3, 4;range(2, 11, 2)给出2, 4, 6, 8, 10。for循环也可以逐个走过字符串或列表:for ch in "banana":。
for i in range(3, 8): 的代码块运行多少次?
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
i 取 3, 4, 5, 6, 7;结束值 8 不包括在内。range(a, b) 运行 $b - a = 8 - 3 = 5$ 次。
把每个 range 与它给出的值配对。
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
一个数是终点;两个数是起点和终点;第三个数是步长,可以是负数。终点值永远不包括在内。
累加器模式
- 要把东西加起来,就在循环之前把总数设为零,在循环之内往上加,在循环之后使用它。
- 如果把
total = 0放在循环里,每一轮都会把它清零,最后只剩最后一个值。
total = 0
for i in range(1, 6):
total += i
print(total) # 15
看总数逐步累加
逐轮执行。i 从 range(1, 6) 中取下一个值,total 加上它,所以第五轮之后总数是 15。
执行 total = 0 和 for p in [4, 8, 15]: total += p 之后,total 是多少?
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
总数依次为 $0 \to 4 \to 12 \to 27$,列表中每一项一步。
while:循环到条件不成立为止
while condition:只要条件为True就一直重复。事先不知道要循环几轮时用它。- 每个
while循环都需要三样东西:一个初始值、一个条件,以及一个让条件逐渐变为False的步进。忘了步进,就会得到死循环(infinite loop)。
运行这段代码会发生什么:n = 5,然后 while n > 0: print(n)?
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
这个循环有初始值和条件,但没有步进。在循环内加上 n -= 1,它就会打印 5, 4, 3, 2, 1 然后停止。
手工追踪
- **跟踪表(trace table)**记录每一轮之后所有变量的值。用它来预测循环,也用它找出你对循环的理解和真实循环在哪里出现分歧。
- 每一轮填一行,并在每行末尾检查条件。循环在第一个
False处停止。

- 对
n = 5追踪 factorial 循环。 - 开始:
n = 5,factorial = 1。每轮之后:$(4, 5)$、$(3, 20)$、$(2, 60)$、$(1, 120)$。 - 这时
n > 1为False,循环结束,打印120。一共四轮,因为n从 5 减到了 1。
追踪:x = 1,然后 while x < 50: x *= 3。循环结束时 x 是多少?
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
$x$ 依次为 $1 \to 3 \to 9 \to 27 \to 81$。在 27 时条件仍为真,于是再运行一次;到 81 时条件为假。
break:任务完成就停下
break立刻离开循环。它适合搜索:逐个查看,找到想要的那个就停下。- 从 100 开始找第一个 7 的倍数,会测试 100、101、102、103 和 104,然后在 105 停下。
for n in range(100, 200):
if n % 7 == 0:
break
print(n) # 105
一个循环执行 for n in range(30, 60):,在第一个满足 n % 8 == 0 的 n 处 break。循环结束后 n 是多少?
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
30 和 31 不是 8 的倍数;32 是,于是 break 停止循环,此时 n 仍等于 32。
用 for 还是 while?
- 轮数已知,或要访问集合里的每一项时,用
for。它不会无限运行。 - 由条件决定何时停止时,用
while:直到余额超过 £2000,直到用户输入有效的数字。上面的存款循环在 15 年后停在 £2078.93,而不是正好落在 £2000。
哪个任务需要 while 循环而不是 for 循环?
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
没人知道用户会输错几次,所以必须由条件决定。另外三个任务访问的是已知的一组项目。
容易丢分的地方
- 差一错误。
range(1, 5)停在4。数一数轮数:range(a, b)运行 $b - a$ 次。 while里没有步进。 如果循环里没有任何东西改变条件,它就永远不会结束。- 累加器放错位置。
total = 0放在循环之前;print(total)通常放在循环之后,不要缩进到循环里。 - 修改
for的循环变量。 在for i in range(5):里设置i = 10并不能跳过轮次;下一轮会重新设置i。
for i in range(1, 5): 在最后一轮时 i 等于 5。
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
最后一个值是 4;终点值永远取不到。要包括 5,应写 range(1, 6)。
你掌握了
- 循环重复执行一个代码块。
for适合次数已知或遍历集合;range(a, b)在b之前停止。 while循环需要初始值、条件和走向False的步进;没有步进就是死循环。- 累加时在循环前设定总数。用
break提前结束搜索,用跟踪表检查任何循环。