1. 遍历
当一段代码需要对列表中的每个元素都执行一次时,可以使用循环。例如,逐个打印学习主题、检查每个订单,或者处理接口返回的多条数据。
如果手动写出每一次操作,代码会重复很多次:
1topics = ["变量", "数据类型", "条件语句"]23print(topics[0])4print(topics[1])5print(topics[2])
当数据数量变化时,这种写法还需要不断修改。for 循环可以把「取出一个元素并执行一次代码」这件事表达出来:
1topics = ["变量", "数据类型", "条件语句"]23for topic in topics:4print(topic)
这段代码会依次取出列表中的三个字符串,并分别赋值给 topic。循环体执行三次,每次处理一个主题。
2. for
for 循环的基本结构是:
1for item in collection:2print(item)
可以把它读成「从 collection 中依次取出元素,把当前元素叫作 item,然后执行缩进的代码」。
Python 使用缩进表示循环体,冒号不能省略:
1names = ["小明", "小红", "小李"]23for name in names:4message = f"你好,{name}"5print(message)67print("所有名字处理完成")
for 循环结束后,程序会继续执行循环体后面的代码。循环变量 name 在每次循环中会被新的元素覆盖。
for 不要求集合必须是列表。元组、集合和字符串都可以被遍历:
1colors = ("红色", "绿色", "蓝色")23for color in colors:4print(color)56for character in "Python":7print(character)
字符串会被逐个遍历其中的字符。实际开发中,先判断自己想处理的是整个字符串,还是字符串中的每个字符,避免误用循环。
3. range
如果只是想重复执行几次,而不是遍历现成的数据,可以使用 range() 生成一组连续的整数:
1for number in range(3):2print(number)
输出是 0、1、2。range(3) 包含 0,但不包含结束值 3。这个「包含开始,不包含结束」的规则非常重要。
range() 也可以指定开始值和结束值:
1for number in range(1, 4):2print(number)
输出是 1、2、3。如果还需要指定每次增加多少,可以传入第三个参数:
1for number in range(0, 10, 2):2print(number)
这段代码输出 0、2、4、6、8,每次增加 2。步长也可以是负数,用来倒序遍历:
1for number in range(3, 0, -1):2print(number)
初学时可以先记住三种常见形式:range(stop)、range(start, stop) 和 range(start, stop, step)。stop 永远不会出现在结果中。
4. 控制
循环中可以配合条件语句,决定当前元素是否需要处理:
1numbers = [1, 2, 3, 4, 5, 6]23for number in numbers:4if number % 2 == 0:5print(f"{number} 是偶数")
break 用来提前结束整个循环。一旦执行到 break,循环后面的元素就不会再处理:
1for number in range(1, 6):2if number == 4:3break4print(number)
这段代码只会打印 1、2、3。break 适合「已经找到结果,不需要继续查找」的场景。
continue 用来跳过本轮循环,直接进入下一轮:
1for number in range(1, 6):2if number == 3:3continue4print(number)
这段代码会跳过 3,但仍然继续打印 4 和 5。continue 适合「当前元素不符合条件,但后面的元素仍然要处理」的场景。
在同一个循环中可以同时使用 if、break 和 continue,但要让每个分支的目的清楚。循环层级太多或条件太长时,可以先把判断拆成变量。
5. 数据
遍历列表时,循环变量直接得到元素,不需要先通过下标访问:
1topics = ["变量", "循环", "函数"]23for topic in topics:4print(topic)
如果确实需要下标,可以使用 enumerate(),它会同时提供位置和元素:
1topics = ["变量", "循环", "函数"]23for index, topic in enumerate(topics, start=1):4print(f"第 {index} 个主题:{topic}")
enumerate() 比 range(len(topics)) 更直接,也不容易写出下标越界的问题。
遍历字典时,直接遍历得到的是键:
1user = {2"name": "小明",3"city": "上海",4}56for key in user:7print(key, user[key])
如果需要同时得到键和值,可以使用 items():
1user = {2"name": "小明",3"city": "上海",4}56for key, value in user.items():7print(f"{key}:{value}")
循环变量只是当前元素的一个名字。修改循环变量,不会自动修改原列表中的元素:
1numbers = [1, 2, 3]23for number in numbers:4number = number * 1056print(numbers) # [1, 2, 3]
如果要生成修改后的列表,应当把新值保存到另一个列表,或者使用后面会学习到的列表推导式。
6. 实例
下面用一个成绩列表统计通过人数。循环负责逐个检查成绩,条件语句负责判断当前成绩是否达到及格线:
1scores = [58, 76, 91, 42, 68]2passed_count = 034for score in scores:5if score >= 60:6passed_count += 178print(f"通过人数:{passed_count}")
如果还需要记录没有通过的成绩,可以在循环中使用 else 分支:
1scores = [58, 76, 91, 42, 68]23for score in scores:4if score >= 60:5print(f"{score}:通过")6else:7print(f"{score}:需要补充练习")
嵌套循环可以处理二维数据,例如一个简单的表格:
01table = [02["姓名", "分数"],03["小明", 82],04["小红", 95],05]0607for row in table:08for value in row:09print(value, end=" ")10print()
外层循环负责处理每一行,内层循环负责处理当前行中的每一列。嵌套循环很有用,但每增加一层,理解和调试的成本都会上升,应当保持数据结构和循环职责清楚。
修改正在遍历的列表容易漏掉元素,因为删除一个元素后,后面的元素会向前移动。更稳妥的做法是遍历副本,或者创建一个新的结果列表:
1numbers = [1, 2, 3, 4, 5]2odd_numbers = []34for number in numbers:5if number % 2 == 1:6odd_numbers.append(number)78print(odd_numbers) # [1, 3, 5]