欢迎光临
我们一直在努力

Python 基础语法(四):循环结构与流程控制

上一章讲完条件判断以后,程序已经可以根据条件选择不同的执行路线。不过,有些代码并不是只执行一次。例如,输出 1 到 10、逐个处理字符串中的字符,或者在用户输入错误时重新询问,这些情况都需要使用循环。

思维导图

在这里插入图片描述

Python 中常用的循环有 while 和 for。while 根据条件决定是否继续执行,for 用来依次取出一组数据中的每个元素。本章还会讲到 range()、嵌套循环、break、continue 和循环中的 else。

在这里插入图片描述

一、循环是怎样执行的

没有循环时,重复输出三次需要写三条语句:

print("开始学习 Python")
print("开始学习 Python")
print("开始学习 Python")

使用循环以后,可以把重复的次数交给程序控制:

for _ in range(3):
print("开始学习 Python")

运行结果没有变化,但是重复次数不再写死在三条相同的语句中。后面需要执行十次时,只需要把 range(3) 改成 range(10)。

循环通常包含两个部分:

  • 循环条件或者需要遍历的数据;
  • 每次循环都要执行的代码块。

循环体仍然通过缩进表示。缩进结束以后,后面的语句就不属于循环了:

for number in range(3):
print(number)

print("循环结束")

输出结果为:

0
1
2
循环结束

二、while 循环

while 会先判断条件。条件为 True 时执行循环体,执行完以后再次判断;条件变成 False,循环才会结束。

基本语法如下:

while 条件:
循环体

例如,输出 1 到 5:

number = 1

while number <= 5:
print(number)
number += 1

运行结果为:

1
2
3
4
5

这段代码的执行过程是:

  • 先把 number 设置为 1;
  • 判断 number <= 5;
  • 条件成立,输出当前的 number;
  • 执行 number += 1;
  • 回到 while,重新判断条件。
  • 当 number 增加到 6 时,条件不再成立,循环结束。

    在这里插入图片描述

    1. 使用 while 累加

    循环不只可以重复输出,也可以不断修改同一个结果。例如,计算 1 到 100 的和:

    number = 1
    total = 0

    while number <= 100:
    total += number
    number += 1

    print(total)

    输出结果为:

    5050

    这里的 number 用来记录当前处理到哪个数字,total 用来保存已经累加的结果。两个变量的作用不同,不要混在一起。

    2. 根据用户输入结束循环

    如果事先不知道循环要执行多少次,可以把用户输入作为结束条件:

    command = ""

    while command != "quit":
    command = input("请输入命令,输入 quit 退出:")
    print("收到命令:", command)

    只要输入的内容不是 quit,程序就会继续询问。输入 quit 后,当前这一次循环仍然会执行后面的 print(),然后在下一次判断时结束。

    如果不希望输出 quit,可以把处理逻辑放到条件判断中:

    command = ""

    while command != "quit":
    command = input("请输入命令,输入 quit 退出:")

    if command != "quit":
    print("收到命令:", command)

    三、无限循环

    while 的条件如果一直为 True,循环就不会自行结束:

    number = 1

    while number <= 5:
    print(number)

    上面的代码没有修改 number,所以 number <= 5 会一直成立。程序会不断输出 1。

    有些程序会主动使用无限循环,再在循环内部决定何时退出:

    while True:
    command = input("请输入命令:")

    if command == "quit":
    break

    print("正在执行:", command)

    这种写法本身没有问题,不过循环内部必须存在能够执行到的退出条件。程序意外进入无限循环时,可以在终端中按 Ctrl + C 停止运行。

    四、for 循环

    for 用来依次取出可迭代对象中的元素。字符串、列表、元组、字典、集合和 range() 生成的整数序列都可以被遍历。

    基本语法如下:

    for 变量 in 可迭代对象:
    循环体

    例如,逐个读取字符串中的字符:

    language = "Python"

    for char in language:
    print(char)

    输出结果为:

    P
    y
    t
    h
    o
    n

    每次循环时,char 会保存当前取出的字符。循环结束以后,字符串中的六个字符都已经处理过一次。

    在这里插入图片描述

    1. 遍历列表

    列表会在后面的章节中详细讲,这里先看它在循环中的基本用法:

    names = ["张三", "李四", "王五"]

    for name in names:
    print("当前用户:", name)

    输出结果为:

    当前用户: 张三
    当前用户: 李四
    当前用户: 王五

    2. 循环变量的命名

    循环变量应该能说明当前取出的内容:

    for student in students:
    print(student)

    for file_name in file_names:
    print(file_name)

    只在很短的计数循环中,才会经常使用 i、j 这样的名称。循环变量完全不会被使用时,可以写成下划线 _:

    for _ in range(3):
    print("重新尝试")

    下划线并没有特殊的语法限制,它只是告诉读代码的人:这个变量不会在循环体中使用。

    五、range() 生成整数序列

    range() 经常和 for 一起使用。它可以接收一个、两个或者三个参数。

    1. range(stop)

    只传一个参数时,序列从 0 开始,到 stop 之前结束:

    for number in range(5):
    print(number)

    输出结果为:

    0
    1
    2
    3
    4

    5 不会包含在结果中。

    2. range(start, stop)

    传入两个参数时,第一个参数是起点,第二个参数是终点:

    for number in range(1, 6):
    print(number)

    输出 1 到 5。仍然需要注意,终点 6 不包含在结果中。

    3. range(start, stop, step)

    第三个参数表示步长:

    for number in range(0, 11, 2):
    print(number)

    输出结果为:

    0
    2
    4
    6
    8
    10

    步长也可以是负数:

    for number in range(5, 0, 1):
    print(number)

    输出结果为:

    5
    4
    3
    2
    1

    使用负步长时,起点必须大于终点。下面的代码不会输出任何内容:

    for number in range(1, 5, 1):
    print(number)

    因为序列需要向下递减,但是起点 1 已经小于终点 5。

    在这里插入图片描述

    4. range 对象

    range() 返回的是一个 range 对象,并不是已经创建好的列表:

    numbers = range(1, 6)

    print(numbers)
    print(type(numbers))

    输出结果为:

    range(1, 6)
    <class 'range'>

    需要查看其中的全部值时,可以临时转换成列表:

    print(list(range(1, 6)))

    输出结果为:

    [1, 2, 3, 4, 5]

    六、同时取得索引和值

    遍历一组数据时,有时还需要知道当前元素的位置。可以使用 enumerate():

    languages = ["Python", "Java", "Go"]

    for index, language in enumerate(languages):
    print(index, language)

    输出结果为:

    0 Python
    1 Java
    2 Go

    enumerate() 默认从 0 开始计数,也可以通过 start 指定起点:

    for number, language in enumerate(languages, start=1):
    print(number, language)

    输出结果为:

    1 Python
    2 Java
    3 Go

    如果只是为了得到索引,不建议写成下面这样:

    for index in range(len(languages)):
    print(index, languages[index])

    这段代码可以运行,但是 enumerate() 更直接,也不需要手动根据索引再次取值。

    七、break 提前结束循环

    break 会立即结束它所在的那一层循环。下面的程序在找到目标数字以后停止查找:

    numbers = [3, 8, 12, 19, 24]
    target = 12

    for number in numbers:
    if number == target:
    print("已经找到:", target)
    break

    print("检查:", number)

    输出结果为:

    检查: 3
    检查: 8
    已经找到: 12

    执行 break 以后,后面的 19 和 24 不会再被检查。

    break 只能写在循环内部。如果循环中还有条件判断,它结束的仍然是循环,不只是 if 代码块。

    八、continue 跳过本次循环

    continue 不会结束整个循环,它只会跳过本次剩余的代码,直接进入下一次循环。

    例如,只输出 1 到 10 中的奇数:

    for number in range(1, 11):
    if number % 2 == 0:
    continue

    print(number)

    遇到偶数时会执行 continue,所以后面的 print() 只会处理奇数。

    在这里插入图片描述

    在 while 循环中使用 continue 时,需要特别注意变量更新的位置:

    number = 0

    while number < 5:
    number += 1

    if number == 3:
    continue

    print(number)

    这里先执行 number += 1,再判断是否跳过。如果把变量更新写在循环末尾,那么执行 continue 时可能跳过更新语句,最后形成无限循环。

    九、循环中的 else

    Python 的 for 和 while 都可以带有 else。当循环正常结束时,else 会执行;如果循环因为 break 提前结束,else 不会执行。

    例如,查找一个数字:

    numbers = [3, 8, 12, 19]
    target = 10

    for number in numbers:
    if number == target:
    print("已经找到")
    break
    else:
    print("没有找到")

    由于列表中没有 10,循环正常遍历结束,最后输出:

    没有找到

    如果把 target 改成 12,循环会执行 break,此时 else 不再执行。

    这里的 else 对应的是 for,所以它的缩进需要和 for 保持一致:

    for 元素 in 数据:
    if 满足条件:
    break
    else:
    没有通过 break 结束时执行

    在这里插入图片描述

    循环中的 else 并不是每段搜索代码都必须使用。如果增加一个布尔变量更容易理解,也可以使用普通写法:

    found = False

    for number in numbers:
    if number == target:
    found = True
    break

    if found:
    print("已经找到")
    else:
    print("没有找到")

    十、嵌套循环

    一个循环里面还可以再写循环。外层循环每执行一次,内层循环都会完整执行一遍。

    例如,输出一个简单的乘法表:

    for row in range(1, 4):
    for column in range(1, 4):
    print(f"{row} × {column} = {row * column}")

    print("—")

    外层循环控制 row,内层循环控制 column。当 row 为 1 时,column 会依次取 1、2、3;接着 row 变成 2,内层循环重新从头开始。

    在这里插入图片描述

    1. break 只结束当前循环

    在嵌套循环中,break 只会结束离它最近的那一层循环:

    for row in range(1, 4):
    for column in range(1, 4):
    if column == 2:
    break

    print(row, column)

    内层循环在 column == 2 时结束,但是外层循环仍然会继续处理下一行。

    如果确实需要同时结束多层循环,可以设置一个状态变量,或者把循环放进函数中,再使用 return 返回。函数会在后面的章节中讲。

    2. 不要写太深的嵌套

    两层循环很常见,例如处理表格中的行和列。嵌套达到三四层以后,代码通常会变得难以阅读。遇到这种情况,可以检查数据结构是否合适,或者把一部分处理拆成函数。

    十一、循环中的变量

    Python 的 for 循环不会创建单独的块级作用域。循环结束以后,循环变量通常仍然可以访问:

    for number in range(3):
    print(number)

    print("循环结束后的 number:", number)

    输出结果为:

    0
    1
    2
    循环结束后的 number: 2

    不过,不要依赖循环结束后保存的最后一个值。如果循环一次都没有执行,变量可能根本不存在:

    for number in range(0):
    print(number)

    print(number) # NameError

    需要在循环之后使用结果时,应该在循环前明确初始化变量。

    十二、综合示例:统计多次输入

    下面的程序接收多次成绩输入,输入 q 时结束,然后输出有效成绩的数量、总分和平均分:

    count = 0
    total = 0.0

    while True:
    text = input("请输入成绩,输入 q 结束:").strip()

    if text == "q":
    break

    if not text:
    print("输入不能为空")
    continue

    score = float(text)

    if score < 0 or score > 100:
    print("成绩应在 0 到 100 之间")
    continue

    total += score
    count += 1

    if count > 0:
    average = total / count
    print(f"共输入 {count} 个有效成绩")
    print(f"总分:{total:.1f}")
    print(f"平均分:{average:.1f}")
    else:
    print("没有输入有效成绩")

    这个例子中,循环次数并不确定,所以使用 while True。输入 q 时通过 break 结束循环;空内容和超出范围的成绩通过 continue 跳过。循环结束以后,还需要先判断 count 是否大于 0,否则直接计算平均分会出现除零错误。

    当前代码假设用户输入的是数字。如果输入 abc,float(text) 会出现 ValueError。异常处理会在后面的章节中单独讲。

    十三、常见错误

    1. 忘记更新 while 条件中的变量

    number = 1

    while number <= 5:
    print(number)

    这段代码会形成无限循环。需要在循环体中更新 number:

    number += 1

    2. 误以为 range() 包含终点

    for number in range(1, 5):
    print(number)

    这里只会输出 1、2、3、4。需要输出到 5 时,终点应该写成 6。

    3. 负步长和起止位置写反

    for number in range(1, 5, 1):
    print(number)

    这段循环不会执行。步长为负数时,起点需要大于终点。

    4. 在 continue 前漏掉变量更新

    number = 0

    while number < 5:
    if number == 2:
    continue

    number += 1

    当 number 变成 2 后,程序会一直执行 continue,再也没有机会更新 number。

    5. 把 break 当成结束所有循环

    嵌套循环中的 break 只结束当前层。需要结束外层循环时,不能只在内层写一个 break。

    6. 修改正在遍历的数据

    遍历列表时直接删除其中的元素,可能跳过部分内容:

    numbers = [1, 2, 3, 4]

    for number in numbers:
    if number % 2 == 0:
    numbers.remove(number)

    对于这种需求,通常会遍历副本,或者生成一个新的列表。等学完列表以后再详细处理。

    7. 循环嵌套过深

    循环本身没有限制只能嵌套两层,但是层级越深,条件和变量越容易混淆。能够拆开的处理不要全部堆在一个循环中。

    十四、练习

    练习一:输出整数

    使用 while 输出 1 到 20,再使用 for 和 range() 完成一次。

    练习二:计算偶数和

    计算 1 到 100 之间全部偶数的和。

    练习三:倒计时

    使用 range() 输出 10 到 1,最后输出 开始。

    练习四:密码重试

    预设一个密码,最多允许用户输入三次。输入正确时输出 登录成功 并结束循环;三次都不正确时输出 尝试次数已用完。

    练习五:查找字符

    接收一个字符串和一个目标字符,找到时输出它第一次出现的位置,没有找到时输出 字符不存在。可以使用 enumerate() 和循环中的 else。

    练习六:九九乘法表

    使用两层 for 循环输出九九乘法表。内层循环的终点需要根据外层循环当前的数字变化。

    练习七:统计输入

    不断接收整数,输入 0 时结束。最后输出正数、负数各有多少个,并计算所有非零数字的总和。

    这一章讲完以后,已经可以使用循环重复处理数据,也可以通过 break 和 continue 改变循环的执行过程。下一章会开始学习列表和元组,包括元素访问、切片、增删改查以及列表复制。

    赞(0)
    未经允许不得转载:171主机测评 » Python 基础语法(四):循环结构与流程控制
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址