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/迭代器的原理在讲迭代器和面向对象时展开。