2.12. 循环¶
循环会反复运行同一段代码。Python 有两种形式:while,只要某个条件保持为真就一直继续;以及 for,它会遍历一个序列中的各个元素。
while 不断测试一个条件;for 则遍历一个序列直到它被耗尽。¶
2.12.1. while 循环¶
while 循环在每次迭代之前测试它的条件,并运行循环体直到测试变为假:
count = 0
while count < 5:
print(count)
count += 1
输出:
0
1
2
3
4
如果条件在开始时为真且永远不会变为假,循环就会永远运行下去。while True: 是主循环的标准写法,通过 break 显式退出:
while True:
step()
if done():
break
2.12.2. for 循环¶
for 循环遍历一个可迭代对象的各个元素 —— 可以是列表、元组、字符串、字节串、字典,或任何其他支持迭代的对象:
for fruit in ["apple", "banana", "cherry"]:
print(fruit)
输出:
apple
banana
cherry
同样的形态也适用于字符串,此时每个元素都是一个单字符的字符串:
for letter in "OpenMV":
print(letter)
输出:
O
p
e
n
M
V
直接迭代字典会按插入顺序产出它的键:
for key in {"a": 1, "b": 2}:
print(key)
输出:
a
b
每一轮都会把循环变量(fruit、letter、key)绑定到下一个元素。循环结束后,该变量仍保留最后一次迭代时的值。
2.12.3. range¶
对于遍历一段数值区间的 for 循环,使用 range():
range(stop)—— 0, 1, ..., stop - 1。range(start, stop)—— start, start + 1, ..., stop - 1。range(start, stop, step)—— 带自定义步长(负值表示倒数)。
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(2, 8, 2): # 2, 4, 6
print(i)
for i in range(10, 0, -1): # 10, 9, ..., 1
print(i)
range() 惰性地产生值 —— 它不会在内存中构建一个列表。要得到一个真正的 list,可以把它包起来:list(range(10))。
2.12.4. enumerate¶
当循环同时需要索引和元素时,enumerate() 会产出 (index, item) 对:
for i, name in enumerate(["a", "b", "c"]):
print(i, name)
# 0 a
# 1 b
# 2 c
通过传入第二个参数可以让索引从零以外的值开始:enumerate(items, start=1)。
2.12.5. zip¶
要同步遍历两个(或更多)可迭代对象,使用 zip()。它在每个位置产出一个元组,并在最短的输入耗尽时停止:
names = ["alice", "bob", "carol"]
scores = [88, 92, 70]
for name, score in zip(names, scores):
print(name, score)
输出:
alice 88
bob 92
carol 70
2.12.6. 使用 := 进行内联赋值¶
海象运算符 := 是一种既是赋值又是表达式的写法。它在绑定一个名称的同时求值为相同的值。在 while 循环中,这把常见的“读取、检查、循环体”模式压缩成了一行:
# without walrus
value = next_value()
while value is not None:
process(value)
value = next_value()
# with walrus
while (value := next_value()) is not None:
process(value)
这两种形式做的是同一件事。当赋值的重复确实损害了可读性时,就采用 :=;不要只为了显得聪明而使用它。在大多数位置都需要加括号,以保持表达式无歧义。