跳转至

5.3 程序结构——循环语句

内容梗概

本课讲循环语句 while 和 for,并结合上次作业(两字符一组解码)回顾点评了同学们的多种解法。while 部分借一个经典动图例子(用 len() 作条件、用 pop() 逐个弹出元素处理列表直到为空)讲解了循环条件与循环变量配合设计的思路。for 部分讲了遍历序列、for + range 的用法,澄清了 range 返回的是可迭代对象而非列表。随后讲解了循环控制关键字 break、continue、循环的 else 以及占位符 pass,并演示了素数查找和“给学号尾号为 5 的同学发邮件”两个例子。

知识点详解

while 循环

  • 语法:while 表达式:(表达式返回 True/False)+ 冒号 + 缩进的循环体 (约 01:17)。
  • 经典示例(网络动图):列表含奇偶数,要求分离到奇数、偶数两个新列表 (约 01:36):
  • 条件用 len(列表)(len 返回列表长度,非 0 即为真);循环体第一句用 pop() 弹出最后一个元素放进 number。
  • 条件与 pop 配合使列表每轮变短(6→5→…→0),循环有明确终止;pop() 是列表方法,取出并移除最后一个元素。
  • 用 if number % 2 == 0: 判奇偶分别放入对应列表。顺带一提:if 条件在 Python 中不必像 C 那样打括号。
  • 老师强调这种“循环条件是某东西的长度、循环中不断减小它”的设计思路值得学习,Python 和 C 都适用 (约 05:01)。

for 循环与 range

  • 经典用法一:for ch in 字符串:——依次取出序列中的每个元素处理。变量名随意(ch/i/x 都行),相当于新定义的变量;被遍历的只要是**序列**即可(字符串、列表、以后学的元组都是序列)(约 07:12–09:37)。
  • 与 C 语言对比:Python 的 for 更高级,直接把序列元素一个个取出,不需要手动维护下标。
  • 用法二:for i in range(start, end, step):——实现 C 式“按范围变化”的循环。range 三个参数与切片类似:start 起始、end 结束(取不到)、step 步长。例:range(0, len(message), 2) 生成 0, 2, 4, … 用来两字符一组取切片 (约 11:39–12:57)。
  • range 不是列表 (约 13:08–15:48):range 返回一个**可迭代对象**(迭代器),每次取出一个值、下次访问取下一个;用 type(range(2)) 打印可看到类型就是 range,不是 list。用 for 时可“脑补”成序列,但必须意识到它不是列表。
  • 想要真列表:用 list(range(0, 6, 2)) 得到 [0, 2, 4](复习之前讲的 list() 用法);也可以用列表推导式 [i for i in range(...)] (约 15:48–17:14)。
  • 作业点评(有创意的解法):有同学不用 range,而是每次 s = s[:2] 取头两个字符后,让 s = s[2:] 把原串本身“截短”,永远只取头两个。思路完全可行,只是每次切片会生成新字符串、空间上略有浪费。老师强调:课上讲的不是标准答案,能跑出结果就赢了,鼓励发挥创意 (约 18:06–20:27)。
  • 顺带提醒:单双引号字符串不要混用,风格要统一 (约 07:43)。

break / continue / else / pass

  • break (约 21:57):提前终止整个循环。示例:找 2–10 内的素数,对每个 n 遍历 x∈[2, n-1],一旦发现 n % x == 0(找到因数)就打印并 break,不必再找其余因数,节省计算开销。另一个例子:表白程序里的 while True 死循环反复随机坐标,直到新坐标满足“不压鼠标”条件就 break (约 25:59)。
  • continue (约 27:26):跳过本轮循环剩余部分,直接进入下一轮。示例:生成 1–99 的学号列表,把学号转成字符串后取末位(s[-1]),若不等于 '5' 就 continue 跳过,否则执行“发邮件”(演示时用 print 代替)——模拟毕业论文抽盲审、给尾号为 5 的同学发邮件的场景。这是 continue 最常见的使用模式。
  • 循环的 else (约 33:56):Python 特有语法,当循环条件不成立(正常结束)时还想做些事,可写在循环的 else: 里。老师坦言暂时没想到贴切的例子,实际用得较少,先记住有这个用法,以后遇到合适例子再补讲。
  • pass (约 36:15):占位符。函数体或循环体语法上不能空着,暂时没想好写什么就用 pass 占位,以后再补。例:while True: pass 是死循环(可按 Ctrl+C 中断);表白程序的 hitme 函数永远不会被执行到,里面写 pass 即可。读开源代码见到 pass 要理解其用途 (约 37:09–40:09)。

示例与演示

  • while 动图示例:奇偶数分离(len + pop + % 2 判断)。
  • for 遍历字符串、for i in range(0, len(message), 2) 结合切片两字符一组处理(呼应上次作业)。
  • print(type(range(2))) 验证 range 类型;list(range(0,6,2)) 转成真列表;列表推导式回顾。
  • 素数查找(低效率解法,仅为演示 break):外层 for 取 n,内层 for 取 x,找到因数即 break。
  • continue 演示:student_id_list = [x for x in range(1, 100)],s = str(id),末位 s[-1] != '5' 则 continue,否则打印(代表发邮件)。

重点与难点

  • while 循环必须保证条件最终能变为假(如配合 pop 缩短列表),否则死循环。
  • range 返回可迭代对象而非列表,是常见误解;end 值取不到(左闭右开)。
  • break 终止整个循环;continue 只跳过本轮——二者区别要清楚。
  • 循环的 else 容易被误解,注意它与“循环正常结束(非 break 退出)”相关,实际用得少。
  • pass 是语法占位符,常见于读别人源码;函数体不能为空。

关联内容

  • 前置:5.1 布尔逻辑(循环条件)、列表及其方法(len、pop、list())、切片、字符串、列表推导式。
  • 紧密结合上次作业(两字符一组解码):while 解法、for+range 解法、切片截短解法都在本课点评;作业用 GitHub 提交,改进后可再次 commit,老师会再点评。
  • 表白程序(5.2)中的死循环+break、hitme 函数+pass 在本课被回顾。
  • 循环的 else 的合适例子、发邮件的具体实现(实践部分)留待后续课程;range/迭代器的原理在讲迭代器和面向对象时展开。