基础

Python 中的循环与条件:for、while、range、enumerate、break、if/elif 和 match/case

更新于: · Skillaria.Top

Python 中的循环用来重复执行操作:for 遍历列表、字符串、字典或 range() 生成的数字,while 则在条件为真时一直执行。break 用于跳出循环,continue 用于跳过本次迭代,enumerate() 提供元素编号。决策由 if/elif/else 条件完成,而 match/case(自 Python 3.10 起)用于按形状拆分数据。

Python 中的循环用来重复执行某个操作:遍历购物清单,处理文件的每一行,或者在用户输入正确的数字之前一直询问。语言中有两种循环——for 和 while,而在循环内部做决定则依靠 if/elif/else 条件以及 match/case 语句。下面通过实际示例,逐一讲解每个工具。

条件:if、elif、else

条件语句只有在表达式为真时才执行代码块。代码块通过 4 个空格的缩进来标识——Python 中没有花括号,缩进错误会立即导致 IndentationError。

spent = 4200
limit = 5000

if spent > limit:
    print("已超出限额")
elif spent > limit * 0.8:
    print("剩余预算不足 20%")
else:
    print("一切正常")

elif 分支从上到下依次检查,只执行第一个满足条件的分支。因此更严格的条件应该放在上面:如果把 spent > limit * 0.8 放在第一位,“超出限额”的提示就永远不会出现。

什么算作真

条件中不一定要写比较式。假值包括 False、None、零(0、0.0)以及空集合:""、[]、{}。其他所有值都是真。因此“列表不为空”的检查可以写得很简短:

expenses = []
if not expenses:
    print("暂时没有支出")

条件可以用 and、or、not 组合,范围检查则适合写成链式比较:if 0 < amount <= 100_000:。对于简短的二选一,还有三元运算符:status = "很多" if spent > limit else "正常"。

for 循环:语法与示例

Python 中的 for 不是 C 语言那样的计数器,而是逐个元素的遍历。它依次取出可迭代对象中的每一个元素:列表、字符串、字典、文件或 range。其他语言中的 foreach,就是 Python 中普通的 for。

expenses = [350, 1200, 89, 4500]
total = 0
for amount in expenses:
    total += amount
print(total)  # 6139

for 循环的语法是:for 变量 in 集合:,然后是带缩进的代码块。循环结束后,变量会保留最后一个值——有时这很有用,但在大型程序中不应依赖这一点。

遍历字符串、列表和字典

字符串逐个字符遍历,列表逐个元素遍历。遍历字典时默认取的是键;要同时获得键和值,使用 .items():

by_category = {"餐饮": 3200, "交通": 900, "电影": 600}

for category, amount in by_category.items():
    print(f"{category}: {amount} ₽")

如果只需要值,使用 .values()。在遍历过程中不能改变字典的大小,否则会得到 RuntimeError: dictionary changed size during iteration。如果需要删除元素,请遍历它的副本:for key in list(d):。

range 函数:按数字循环

需要遍历数字时,可以使用 range()。它不会在内存中创建列表,而是逐个生成数字,因此 range(10**9) 可以瞬间创建。

调用生成的数字
range(5)0, 1, 2, 3, 4
range(2, 6)2, 3, 4, 5
range(0, 10, 3)0, 3, 6, 9
range(5, 0, -1)5, 4, 3, 2, 1

关键规则:右边界不包含在内。range(1, 10) 结束于 9——这是“差一错误”的常见原因。步长可以是负数,但不能为零。

for i in range(1, 4):
    print(f"第 {i} 天")
# 第 1 天
# 第 2 天
# 第 3 天

enumerate:循环中的计数器

新手常常写 for i in range(len(items)) 来获得元素的编号。这样也能工作,但可读性较差。函数 enumerate() 会返回“编号、元素”的配对,参数 start 决定从哪个数字开始计数:

items = ["咖啡", "打车", "午饭"]
for n, item in enumerate(items, start=1):
    print(n, item)
# 1 咖啡
# 2 打车
# 3 午饭

要同时遍历两个列表,使用 zip():for name, price in zip(names, prices):。它在最短的列表结束时停止;从 Python 3.10 起,可以传入 strict=True,这样长度不一致时会报错。

Python 中的 while 循环

while 循环在条件为真时重复执行代码块。当重复次数事先未知时,就使用它:等待正确的输入,读取数据直到结束,或者不断重试直到成功。

balance = 10_000
month = 0
while balance > 0:
    balance -= 2_700
    month += 1
print(f"钱够用 {month} 个月。")  # 4

主要风险是忘记修改条件中用到的变量,这样循环永远不会结束。如果程序“卡死”了,按 Ctrl+C,Python 会以 KeyboardInterrupt 中断执行。

无限循环与 do while

有时会有意编写无限循环:while True:,再通过 break 退出。Python 中没有 do while 语句,这种写法就是它的替代:循环体至少执行一次,条件检查放在末尾。

while True:
    raw = input("金额:")
    if raw.isdigit():
        amount = int(raw)
        break
    print("请输入整数")

for 循环很少会变成无限循环——只有在遍历无限迭代器时才会,例如 itertools.count()。

break 与 continue:跳出循环与跳过迭代

break 立即终止循环,程序接着执行循环之后的代码。continue 跳过当前迭代的剩余部分,直接进入下一次迭代。

expenses = [350, -10, 1200, 0, 99_999, 89]

for amount in expenses:
    if amount <= 0:
        continue          # 跳过本次迭代
    if amount > 50_000:
        print("金额可疑,停止")
        break             # 跳出循环
    print(amount)

上面的代码会输出 350 和 1200,然后打印提示信息——循环永远到不了 89。这两个语句只作用于它们所在的最内层循环。

循环的 else

for 和 while 都有一个不常见的 else 分支:只有当循环自然结束、没有被 break 中断时才会执行。这在查找时很方便:

for amount in expenses:
    if amount > 50_000:
        print("找到了一笔大额支出")
        break
else:
    print("没有大额支出")

嵌套循环

循环中嵌套循环时,内层循环会在外层的每一次迭代中完整执行一遍。用这种方式遍历表格、矩阵或成对的元素。

for row in range(1, 4):
    for col in range(1, 4):
        print(row * col, end="\t")
    print()

需要注意两点。第一,运算量增长很快:两层循环各遍历 10 000 个元素,就是 1 亿次操作。第二,break 只能跳出内层循环。若要同时结束两层循环,把循环放进函数里,用 return 返回——这比使用标志变量更清晰。

match/case 语句

自 Python 3.10 起,冗长的 if cmd == ... elif ... 链可以用 match 语句(PEP 634)替代。它不只是 switch:它会把值与模式按结构进行匹配,并同时把各部分拆分到变量中。

def parse(text):
    match text.split():
        case ["add", item, amount]:
            return f"添加 {item}: {amount}"
        case ["list"] | ["ls"]:
            return "显示支出"
        case ["quit"]:
            return "退出"
        case _:
            return "未知命令"

print(parse("add 咖啡 250"))  # 添加 咖啡: 250
print(parse("add 咖啡"))      # 未知命令

列表模式 ["add", item, amount] 只会匹配恰好三个元素、且第一个为 "add" 的列表。因此没有金额的命令会落入 _ 分支,它接收所有其他情况。符号 | 用来合并多个备选项。

字典、类型与守卫条件

字典模式只检查列出的键,多余的键会被忽略。int(a) 这样的写法既检查类型,又捕获值;模式后面的 if 则增加额外条件(守卫,guard):

match event:
    case {"type": "expense", "amount": int(a)} if a > 10_000:
        print("大额支出", a)
    case {"type": "expense", "amount": int(a)}:
        print("支出", a)

match 的主要陷阱

case 中单独的名字是捕获变量,而不是与变量比较。case limit: 会匹配任何值,并把它写入 limit。要和常量比较,应使用带点的名字,例如 case Color.RED:,或使用字面量。

自 3.10 起,match 的语法几乎没有变化。Python 3.15 修正了一处小的不对称:过去字面量模式中只允许数字前面带负号,现在也可以写 case +1:。在较旧的版本中,这样的代码会产生语法错误。

循环中的常见错误

  • 在遍历时修改列表。 在 for 中删除元素会跳过相邻的元素。更好的做法是生成一个新列表:clean = [x for x in items if x > 0]。
  • range 的边界。 range(1, n) 不包含 n。
  • while 中忘记修改条件——导致无限循环。
  • 在循环中用 += 拼接字符串,数据量大时比 "".join(parts) 慢。
  • 把赋值当作比较:if x = 5 是语法错误,比较应写作 ==。

循环练习题

  1. 计算一个支出列表的总和与平均值,跳过负数。
  2. 用嵌套循环输出 1–9 的乘法表。
  3. 不断询问用户输入数字,直到输入空字符串,然后输出最大值。
  4. 在列表中找出第一个大于 1000 的数;如果没有,给出提示(使用 for ... else)。
  5. 用 match 解析命令 add、del、list。

小结

Python 的循环归结为两种结构:for 遍历集合或 range(),while 在条件成立期间持续执行。break 和 continue 控制循环的流程,enumerate() 和 zip() 省去手动计数,而 if/elif/else 和 match/case 负责做出决定。课程中的支出记录器项目会在实践中用到所有这些工具。

常见问题

for 和 while 在 Python 中有什么区别?

for 遍历现成的序列,自己知道何时结束;while 只要条件为真就重复执行。如果重复次数已知或有集合可遍历,用 for;如果在等待某个事件,用 while。

如何倒序遍历循环?

对集合使用 reversed(items),对数字使用 range(n - 1, -1, -1)。reversed 不会复制列表,而是从末尾开始遍历。

Python 中有 switch 吗?

没有单独的 switch,它的作用由 if/elif 链以及 Python 3.10 引入的 match/case 实现。match 的功能更强:可以按结构拆分列表和字典,并捕获值。

循环和列表推导式哪个更快?

形如 [x * 2 for x in items] 的列表推导式通常比等价的 append 循环略快,而且更简短。涉及多个条件的复杂逻辑,用普通循环更易读。

如何一次跳出两层嵌套循环?

break 只跳出内层循环。最简单的办法是把循环放进一个函数中,然后用 return 退出。

通过视频学习本主题

课程“Python 3.15: от новичка до профи”结合实践详细讲解了这一主题。

前往课程