一、为什么需要循环
先做个小实验。要在屏幕上打印 5 遍「我要学 Python」,最直接的办法是抄 5 行:
print('我要学 Python')
print('我要学 Python')
print('我要学 Python')
print('我要学 Python')
print('我要学 Python')
能跑,但很笨。那要打印 100 遍呢?抄 100 行吗?
这时候就该请出循环了:把「要重复做的事」只写一遍,再告诉 Python 重复多少次。
for i in range(5):
print('我要学 Python')
5 行变 2 行。想改成 100 遍,只要把 5 改成 100。这就是循环最大的价值:重复的事只写一遍。
循环的三要素
不管哪种循环,脑子里都要有这三样东西:
| 要素 | 含义 | 例子(从 1 数到 5) |
|---|---|---|
| ① 起点 | 从哪儿开始 | 从 1 开始 |
| ② 条件 | 什么时候还继续 | 只要还没超过 5 |
| ③ 变化 | 每转一圈往终点靠近一点 | 每次加 1 |
三要素里最容易漏掉的是 ③ 变化。忘了它,条件永远成立,程序就会一直转下去——这叫死循环,后面第十二节专门讲怎么处理。
两种循环,两种长相
| 写法 | 一句话理解 | 适合什么场景 | 典型例子 |
|---|---|---|---|
for | 把一串东西挨个过一遍 | 事先知道要遍历什么 | 遍历列表、字符串、range() |
while | 条件成立就一直转 | 靠条件决定停不停 | 猜数字、输入到某个字符才退出 |
下面先讲 for,再讲 while,最后讲循环里两个「紧急刹车」——break 和 continue。
课程思政|科技自立自强 · 重复交给机器,判断留给人
打印 100 遍不用抄 100 行,把重复的部分写一遍、交给 for 转就行。机器最擅长的,就是把同一件事做上一万遍也不喊累,而人该把力气花在「要不要重复、怎么重复」这些判断上。想想工业软件、自动化产线为什么是硬骨头——谁能让机器替人扛下重复,谁就真正握住了主动权。学循环,也是在学怎么把力气用在刀刃上。
二、for 循环:把一串东西挨个过一遍
for 循环的长相,就是把「一串东西」交给它,它一个一个拿出来用:
# 示意:把「一串东西」换成真实的列表、字符串或 range(...)
for 变量 in 一串东西:
要重复做的事(记得缩进)
这是长相,不是能直接跑的代码——一串东西 还没定义呢。看几个真能跑的:
for char in 'Hello':
print(char)
输出:
H
e
l
l
o
把 'Hello' 看成 5 个字符排成的队,for 就是从头到尾依次取出一个交给 char,取完了就结束。
换成列表也一样。列表就是前面学过的、用方括号装一串东西:
hotpot = ['毛肚', '肥牛', '虾滑', '鸭肠']
for dish in hotpot:
print('下锅:', dish)
输出:
下锅: 毛肚
下锅: 肥牛
下锅: 虾滑
下锅: 鸭肠
元组(用圆括号装一串东西)也能遍历:
for n in (1, 2, 3):
print(n)
输出 1、2、3。
每一圈发生了什么
上面那个火锅配菜的例子,一圈一圈拆开是这样的:
| 第几圈 | dish 的值 | 打印出来的话 |
|---|---|---|
| 第 1 圈 | 毛肚 | 下锅: 毛肚 |
| 第 2 圈 | 肥牛 | 下锅: 肥牛 |
| 第 3 圈 | 虾滑 | 下锅: 虾滑 |
| 第 4 圈 | 鸭肠 | 下锅: 鸭肠 |
| 没有第 5 圈 | —— | 列表取完了,循环结束 |
循环变量起什么名字
for 后面那个变量叫循环变量,每转一圈它就换成下一个元素。名字自己起,但建议起得能看懂:
| 写法 | 评价 |
|---|---|
for fruit in fruits: | 很好,一看就知道装的是水果 |
for s in scores: | 很好,s 是分数的意思 |
for i in range(5): | 可以,约定俗成 i 表示序号/计数 |
for x in fruits: | 能用,但 x 看不出是什么 |
循环结束后,变量还在
这一点新手常常想不到:循环变量不是只在循环里面有效,循环结束后它仍然是最后一个值。
for i in range(3):
pass
print('循环结束后 i =', i)
输出 循环结束后 i = 2。因为 range(3) 给出 0、1、2,最后一圈 i 是 2。
for 默认交出的是键。d = {'姓名': '小明', '年龄': 18},写 for k in d: 会依次得到 '姓名'、'年龄',还可以用 d[k] 取出对应的值。三、range():批量造出数字
上一个例子里的 range(5) 是造一串数字用的。程序里要「重复 10 次」「从 1 加到 100」都靠它。
它本身不是列表,用 list() 包一下才能看见里面是什么:
print(list(range(5)))
输出 [0, 1, 2, 3, 4]。注意:从 0 开始,到 5 结束但不包含 5。
四种常见写法
| 写法 | 产出的数字 | 什么时候用 |
|---|---|---|
range(5) | 0, 1, 2, 3, 4 | 重复 5 次,或从 0 开始数 |
range(1, 6) | 1, 2, 3, 4, 5 | 从 1 数到 5 |
range(1, 11, 2) | 1, 3, 5, 7, 9 | 隔一个取一个 |
range(10, 0, -1) | 10, 9, 8 … 1 | 倒着数 |
挨个跑一遍看结果:
print(list(range(5)))
print(list(range(1, 6)))
print(list(range(1, 11, 2)))
print(list(range(10, 0, -1)))
输出:
[0, 1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 3, 5, 7, 9]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
三条必须记住的规则
- 终点不包含。想数到 5,得写
range(1, 6);想数到 100,得写range(1, 101)。这是新手出错最多的地方。 - 只写一个数字时,从 0 开始。
range(5)就是range(0, 5)。 - 第三个数字是「步长」,默认 1。写
-1就能倒着数。
for i in range(5, 1):屏幕上什么也不显示,程序直接跳到循环后面。倒着数必须写
range(5, 0, -1)。range 到底给出几个数,用 len() 数一数即可:len(range(1, 101)) 的结果是 100。四、循环的四个基本功
循环用得最多的四件事,记成四个「模板」就行。以后遇到类似题目,直接往里套。
基本功 1:累加(把一串数加起来)
套路是:先在循环外面准备一个「零钱罐」变量,循环里往里扔。
total = 0
for i in range(1, 101):
total += i
print('1~100 的和是', total)
输出 1~100 的和是 5050。
total += i 要写在循环体里面(缩进四格)。写在循环外面就只加最后一次。基本功 2:计数(数一数有多少个)
和累加几乎一样,只不过每次加的是 1。比如数一句话里出现了几个「吃」字:
text = '我想吃火锅想吃烧烤想吃炸鸡'
count = 0
for ch in text:
if ch == '吃':
count += 1
print('「吃」字出现了', count, '次')
输出 「吃」字出现了 3 次。
基本功 3:找最大(最值)
套路是:先假定第一个就是最大的,然后拿后面的一个个来挑战。
scores = [88, 92, 75, 96, 81]
best = scores[0]
for s in scores:
if s > best:
best = s
print('最高分是', best)
输出 最高分是 96。
best = scores[0] 写成 best = 0。如果所有分数都是负数,0 永远「最大」,结果就错了。先拿第一个当擂主最保险。基本功 4:求平均
先用累加求出总和,再除以个数(个数用 len() 数)。
scores = [88, 92, 75, 96, 81]
total = 0
for s in scores:
total += s
print('平均分是', total / len(scores))
输出 平均分是 86.4。
sum() 和 max(),sum(scores) 直接得到 432、max(scores) 直接得到 96,效果和上面一样。但循环版本一定要会写——以后要统计的不是「加起来」而是更复杂的规则时,现成函数帮不上忙。课程思政|工匠精神与严谨求实 · 零钱罐要先归零
累加前要把「零钱罐」变量先设成 0,而且 total += i 必须写在循环体里面——这两步错一步,结果就全错。真正的功夫,往往就藏在这些看起来最简单的地方。找最大最小时也一样,先假定第一个,再让后面一个个来挑战,别一上手就想当然。把每个基本功练到不用想就对,复杂的数据处理才站得稳。
五、while 循环:条件成立就一直转
for 是「有一串东西要过一遍」,while 是「条件成立就一直转」。三要素在写法上看得特别清楚:
# 示意:三要素缺一不可
变量 = 起点值 # ① 起点
while 条件: # ② 条件成立就继续转
要重复做的事
变量 = 变量 + 1 # ③ 变化:往终点靠近
把「从 1 加到 100」用 while 写一遍:
total = 0
i = 1
while i <= 100:
total += i
i += 1
print('1~100 的和是', total)
输出 1~100 的和是 5050,和 for 版结果一模一样。
倒计时
i = 3
while i > 0:
print(i)
i -= 1
print('发射!')
输出 3、2、1、发射!。
一直收到 0 才停(次数事先不知道)
这是 while 真正的用武之地——要转多少圈,得看用户输入几次:
total = 0
num = int(input('输入一个数字(输入 0 结束):'))
while num != 0:
total += num
num = int(input('输入一个数字(输入 0 结束):'))
print('所有输入数字的总和是:', total)
运行起来是这样(输入 5、8、0):
输入一个数字(输入 0 结束):5
输入一个数字(输入 0 结束):8
输入一个数字(输入 0 结束):0
所有输入数字的总和是: 13
input() 读进来的都是字符串,要和数字比较或做加法,必须先 int() 转换,否则会报 TypeError: '>' not supported between instances of 'str' and 'int'。猜数字游戏
循环次数事先完全不知道,转到猜对为止:
import random
random.seed(42) # 固定随机结果,方便对照,写程序时可以不写
target = random.randint(1, 10)
guess = None # 先随便给一个和答案不同的值
while guess != target:
guess = int(input('猜一个 1~10 之间的数字:'))
if guess < target:
print('猜小了!')
elif guess > target:
print('猜大了!')
print('恭喜,猜中了!')
猜 5、1、2 时是这样(seed(42) 之后答案固定是 2):
猜一个 1~10 之间的数字:5
猜大了!
猜一个 1~10 之间的数字:1
猜小了!
猜一个 1~10 之间的数字:2
恭喜,猜中了!
guess = None 这一句别省。None 表示「什么都没有」,先用它占个位置,保证第一次 guess != target 一定成立,循环能顺利进得去。while True:故意不写条件
while True 意思是「永远转下去」,退出全靠循环里的 break(下一节讲)。
这是写菜单、命令行程序最常用的长相:
i = 1
while True:
print(i)
i += 1
if i > 3:
break
输出 1、2、3。循环里必须有一条能 break 出去的路,
否则就是死循环,只能按 Ctrl + C 强行停下。
六、for 还是 while
两个都能实现「从 1 加到 100」,那到底用哪个?看你的依据是什么。
for | while | |
|---|---|---|
| 依据 | 我有一串东西要挨个过 | 我有个条件,成立就继续 |
| 圈数 | 由那串东西的长度决定 | 由条件什么时候不成立决定 |
| 圈数事先知道吗 | 基本知道 | 常常不知道 |
| 最怕什么 | 写错 range 的终点 | 忘了改变量 → 死循环 |
| 典型场景 | 遍历列表/字符串、重复 N 次、累加 1~N | 猜数字、输入到某字符退出、菜单循环 |
同一道题两种写法对照(1~100 累加):
# for 版:我清楚要过一遍 1~100 这些数字
total = 0
for i in range(1, 101):
total += i
print(total)
# while 版:我关心「还没到 100 就继续」
total = 0
i = 1
while i <= 100:
total += i
i += 1
print(total)
两句都输出 5050。
for,只能说出「满足什么条件」就用 while。遍历列表、字符串一律用 for,别去写 for i in range(len(x)) 绕一圈。七、break:提前收工
break 的意思是「不转了,立刻收工」——跳出整个循环,接着执行循环后面的代码。
# 示意
for 变量 in 一串东西:
if 某个条件:
break # 整个循环到此结束
其他要重复的事
在 for 里用:找到 5 就收工,所以只打印到 4。
for i in range(1, 11):
if i == 5:
break
print(i)
输出:
1
2
3
4
在 while 里用:数到 7 就收工。
num = 1
while num <= 10:
if num == 7:
break
print(num)
num += 1
输出 1 到 6。
最常见的用法:找到第一个就停
想找 1~99 里第一个能被 7 整除的数,找到了就没必要往下找了:
for i in range(1, 100):
if i % 7 == 0:
print('第一个能被 7 整除的数是', i)
break
输出 第一个能被 7 整除的数是 7。
输入类程序:用 break 当出口
while True:
cmd = input('请输入命令(q 退出):')
if cmd == 'q':
break
print('你输入了', cmd)
print('程序结束')
运行效果(先输入 3、再输入 q):
请输入命令(q 退出):3
你输入了 3
请输入命令(q 退出):q
程序结束
break 只管最近的那一层循环。如果有两层嵌套,内层 break 之后外层照样继续转——想一次跳出两层,得在外层再加一个判断(或者用一个「标志变量」)。八、continue:跳过这一次
continue 是「这一圈不算,直接开始下一圈」。它不结束循环,只是跳过本圈剩下的代码。
# 示意
for 变量 in 一串东西:
if 某个条件:
continue # 本圈剩下的代码不执行了,直接下一圈
其他要重复的事
只打印奇数:遇到偶数就跳过本次的 print(i)。
for i in range(1, 11):
if i % 2 == 0:
continue
print(i)
输出:
1
3
5
7
9
在 while 里跳过 3 的倍数:
num = 0
while num < 10:
num += 1
if num % 3 == 0:
continue
print(num)
输出 1、2、4、5、7、8、10,3、6、9 都被跳过了。
while 里用 continue 有个大坑:如果「改变量」那一句正好排在 continue 后面,它永远轮不到执行,条件永远成立——变成死循环。所以
num += 1 建议写在 continue 前面(像上面那样),或者干脆改用 for。break 与 continue 对照
break | continue | |
|---|---|---|
| 一句话 | 整个循环不要了 | 只要跳过这一圈 |
| 本圈剩下的代码 | 不执行 | 不执行 |
| 下一圈 | 不会再有了 | 照常继续 |
| 循环后面的代码 | 接着执行 | 等循环正常结束才执行 |
| 经典场景 | 找到目标就收工 | 过滤掉不需要的数据 |
同一组气温里跳过零下的:
temps = [3, -1, 5, -2, 8]
for t in temps:
if t < 0:
continue
print(t)
输出 3、5、8。
九、pass:什么都不做的占位符
pass 是 Python 里唯一一个「什么都不做」的语句。它不打印、不算数、不改任何变量——放在那里,纯粹就是占个位置。
为什么需要这么个「废话」?因为 Python 靠缩进划分代码块,冒号后面必须真的写上代码。有时候结构已经想好了,但某一路暂时没什么要做的,又不能空着,这时就用 pass 顶住。
# 示意:位置先占住,等想好了再把 pass 换成真正要做的事
if 条件1:
pass
else:
其它分支要做的事,想好了写在这里
反过来,冒号后面真的什么都不写,Python 会立刻报错:
if True:
print(1)
IndentationError: expected an indented block after 'if' statement on line 1
原因:Python 没有花括号 {} 来圈住代码块,它用缩进。冒号后面缩进一级的那些行,就是「这个分支的内容」;一行都没有,Python 就不知道这个分支到底存不存在。pass 提供的正是「一行,但什么都不做」。
案例 1:先把结构搭起来
还没想好「及格了要干嘛」,就用 pass 先占着,程序照样能跑。
score = 55
if score >= 60:
pass # 及格的同学暂时不处理,先留个位置
else:
print('成绩不合格,需要补考')
print('检查结束') # 分支走完,程序继续往下
输出:
成绩不合格,需要补考
检查结束
案例 2:循环里用 pass,什么都不会被跳过
for i in range(1, 6):
if i == 3:
pass # 第 3 圈先放着,什么都不做
print('第', i, '圈')
输出:
第 1 圈
第 2 圈
第 3 圈
第 4 圈
第 5 圈
第 3 圈照样打印出来了——pass 什么都没影响。
pass 不会跳过任何东西。它只是「站在这儿什么也不干」——pass 后面的代码、以及这一圈剩下的代码,全都照常执行。案例 3:pass 和 continue 到底差在哪
同一段需求写成两版,一眼就能看出区别:上面「第 2 圈也照样走完」,下面「第 2 圈就此打住」。
for i in range(1, 4):
if i == 2:
pass
print('第', i, '圈')
输出:
第 1 圈
第 2 圈
第 3 圈
for i in range(1, 4):
if i == 2:
continue
print('第', i, '圈')
输出 第 1 圈、第 3 圈——第 2 圈的 print 被跳过了。
一句话总结:pass 是「这一圈也照样走完」,continue 是「这一圈就到此为止」。
pass / continue / break 三兄弟对照
pass | continue | break | |
|---|---|---|---|
| 一句话 | 什么都不做 | 跳过这一圈 | 整个循环不要了 |
| 本圈剩下的代码 | 照常执行 | 不执行 | 不执行 |
| 下一圈 | 照常继续 | 照常继续 | 不会再有了 |
| 循环后面的代码 | 等循环正常结束 | 等循环正常结束 | 立刻接着执行 |
| 典型用途 | 占位、留白 | 过滤掉不要的数据 | 找到目标就收工 |
案例 4:把不认识的情况先放过去
while True:
cmd = input('请输入命令:')
if cmd == 'q':
break
elif cmd == 'show':
print('显示数据')
else:
pass # 其它命令暂时不处理,也不报错
print('结束')
运行效果(依次输入 show、hello、q):
请输入命令:show
显示数据
请输入命令:hello
请输入命令:q
结束
pass 变成偷懒的借口。它只适合「暂时」占位——想好之后一定要回头把 pass 换成真正的代码。如果这个分支本来就什么都不用做,更干净的做法是直接把这一路删掉,而不是留一个空的 pass。pass 全是小写,写成 Pass 会报 NameError: name 'Pass' is not defined;写成 pass() 会报 SyntaxError——它是语句,不是函数,后面不能带括号。另外,以后学函数时会再见到它:
def 定义了一个暂时不写内容的函数,函数体里同样要用 pass 顶住。十、循环套循环(嵌套)
循环体内还可以再写一个循环。外面的管「第几行」,里面的管「这一行有几个」——这是嵌套循环最好用的思路。
for i in range(1, 6):
for j in range(i):
print('*', end='') # end='' 表示不换行
print() # 一行结束后换行
输出:
*
**
***
****
*****
print() 默认会换行,print('*', end='') 把结尾改成空字符串就不换行了;一行拼完再用一句空的 print() 换行。这是打图形、打表格的标准套路。九九乘法表(前四行)
for i in range(1, 5):
for j in range(1, i + 1):
print(f'{j}x{i}={i * j}', end=' ')
print()
输出:
1x1=1
1x2=2 2x2=4
1x3=3 2x3=6 3x3=9
1x4=4 2x4=8 3x4=12 4x4=16
把 range(1, 5) 改成 range(1, 10),就是完整的九九乘法表。第 i 行的诀窍在于内层写的是 range(1, i + 1)——行号越大,这一行的算式越多。
嵌套里的一圈一圈
外层 i | 内层 j 依次取到 | 打印 |
|---|---|---|
| 1 | 1 | 1x1=1 |
| 2 | 1, 2 | 1x2=2 2x2=4 |
| 3 | 1, 2, 3 | 1x3=3 2x3=6 3x3=9 |
| 4 | 1, 2, 3, 4 | 1x4=4 2x4=8 3x4=12 4x4=16 |
break 和 continue 只作用在它所在的那一层。下面这段里内层一遇到 j == 2 就 break,但外层照转,所以打印出 1 1、2 1、3 1:for i in range(1, 4): / for j in range(1, 4): / if j == 2: break / print(i, j)AI 助手小贴士|嵌套循环是循环的 boss 关,让 AI 把执行轨迹摆成表格看。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:用文字表格演示九九乘法表双重循环的执行顺序:外层 i=1 时内层 j 循环几次、各打印什么,最后一共打印多少行
课程思政|诚信与职业操守 · 表要一行行对齐
九九乘法表外层管第几行、内层管这一行有几句,行号越大算式越多,一格都不能错位。打表如此,做报表也一样——每一格背后都是一个真实的数。我们统计人往后要面对的是成绩单、财务报表、调查数据,行列一错、口径一乱,别人就会照着错误的结论去做决定。先把这张乘法表对齐,是诚实对待每一个数字的起点。
十一、十个能直接跑的小案例
下面十个例子都很短,建议每个都亲手敲一遍、跑一遍。
1. 1~100 全部加起来
total = 0
for i in range(1, 101):
total += i
print(f'1~100 的和是 {total}')
输出 1~100 的和是 5050。
2. 1~100 里所有偶数加起来
total = 0
for i in range(1, 101):
if i % 2 == 0:
total += i
print(f'1~100 的偶数和是 {total}')
输出 1~100 的偶数和是 2550。
3. 数一数字符串里有几个指定字符
text = '我想吃火锅想吃烧烤想吃炸鸡'
count = 0
for ch in text:
if ch == '吃':
count += 1
print(f'「吃」字出现了 {count} 次')
输出 「吃」字出现了 3 次。
4. 找出一组分数里的最高分
scores = [88, 92, 75, 96, 81]
best = scores[0]
for s in scores:
if s > best:
best = s
print(f'最高分是 {best}')
输出 最高分是 96。
5. 求平均分
scores = [88, 92, 75, 96, 81]
total = 0
for s in scores:
total += s
average = total / len(scores)
print(f'共 {len(scores)} 人,平均分 {average}')
输出 共 5 人,平均分 86.4。
6. 统计及格和不及格的人数
scores = [88, 55, 72, 40, 91]
passed = 0
failed = 0
for s in scores:
if s >= 60:
passed += 1
else:
failed += 1
print(f'及格 {passed} 人,不及格 {failed} 人')
输出 及格 3 人,不及格 2 人。两个计数器可以并排放,各数各的。
7. 求阶乘(5 的阶乘 = 1×2×3×4×5)
累加的零钱罐设成 0,累乘要设成 1:
n = 5
result = 1
for i in range(1, n + 1):
result *= i
print(f'{n} 的阶乘是 {result}')
输出 5 的阶乘是 120。
8. 打印斐波那契数列前 8 项
a, b = 0, 1
for i in range(8):
print(a, end=' ')
a, b = b, a + b
输出 0 1 1 2 3 5 8 13。每一项都是前两项之和。
9. 找水仙花数(100~999 内)
水仙花数指「各位数字的立方和等于自己」,比如 153 = 1³ + 5³ + 3³:
for n in range(100, 1000):
a = n // 100 # 百位
b = n // 10 % 10 # 十位
c = n % 10 # 个位
if a ** 3 + b ** 3 + c ** 3 == n:
print(n, end=' ')
输出 153 370 371 407,一共 4 个。
10. 判断一个数是不是质数
质数只能被 1 和自己整除。只要在 2 到 n - 1 之间找到一个能整除它的数,就可以立刻下结论:
n = 29
is_prime = True
for i in range(2, n):
if n % i == 0:
is_prime = False
break
if is_prime:
print(f'{n} 是质数')
else:
print(f'{n} 不是质数')
输出 29 是质数。把 n 改成 35,输出 35 不是质数。
十二、最容易踩的六个坑
坑 1:死循环——程序卡住不动了
while 的条件永远成立,程序就会一直转。最常见的两个原因:
# 原因一:循环里忘了改变量,i 永远是 1
i = 1
while i <= 3:
print('永远在转')
# 原因二:continue 跳过了改变量的那一句
i = 0
while i < 5:
if i == 2:
continue # 一到 2 就回到开头,i 永远到不了 3
print(i)
i += 1
Ctrl + C 可以强行停下,屏幕上会出现 KeyboardInterrupt。这不是你写错了语法,而是你主动按停的——看到它就是「死循环被中断了」。预防办法:写
while 时先问自己一句「变量在哪一步变小/变大,最后一定会让条件不成立?」坑 2:range 的终点不包含
| 想要的效果 | 正确写法 | 写成这样会怎样 |
|---|---|---|
| 数到 5 | range(1, 6) | range(1, 5) 只到 4 |
| 数到 100 | range(1, 101) | range(1, 100) 只到 99 |
| 数到 n | range(1, n + 1) | range(1, n) 少了 n |
range(1, n + 1)。坑 3:缩进决定谁在循环里
for i in range(3):
print('在循环里(打印 3 次)')
print('在循环外(只打印 1 次)')
第 2 行缩进四格,属于循环体;第 3 行顶格写,属于循环之后。挪动 4 个空格,执行次数完全不同。
TabError。Python 社区的习惯是统一用 4 个空格,IDLE 里敲 Tab 会自动转成 4 个空格。坑 4:for 循环里改循环变量没用
下面这段你以为会打印 0 然后就跳到 10,实际上是 0、1、2:
for i in range(3):
print(i)
i = 10 # 改了也没用,下一圈重新从 range 里取值
因为 for 每转一圈都会重新把序列里的下一个值赋给 i,你在循环体里的赋值会被冲掉。
"想控制进程请用 break 或 continue;while 里改变量才是有效的(那正是它的「变化」要素)。
坑 5:边遍历边删列表
nums = [1, 2, 3, 4]
for n in nums:
if n == 2:
nums.remove(n)
print(nums)
结果是 [1, 3, 4]——2 是删掉了,但 3 被跳过了。删掉元素后,后面的元素会往前挪一位,循环的下标也跟着走,正好错过一个。
keep = [],循环里满足条件就 keep.append(x),遍历完再 nums = keep。坑 6:想遍历数字却忘了 range
# 错误:5 是个数字,不是一串东西
for i in 5:
print(i)
报 TypeError: 'int' object is not iterable。改成 for i in range(5): 就好了。
for 后面必须跟「一串东西」:列表、字符串、元组、range() 都可以,单个数字不行。
AI 助手小贴士|循环的 bug 千篇一律:死循环、差一错误。练「找 bug」眼力。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:出 3 道找 bug 题:每段循环代码里藏着一个死循环或差一错误,让我先找出来再对答案
十三、报错手册
下面这些报错都是真实运行出来的,照抄本机解释器的原文。看到眼熟的,直接对照处理。
照抄出来的报错
for i in 5:
print(i)
TypeError: 'int' object is not iterable
原因:for 后面必须跟一串东西。改成 for i in range(5):。
for i in range(1, 5.0):
print(i)
TypeError: 'float' object cannot be interpreted as an integer
原因:range() 只收整数。小数要先 int() 转换,或者改用别的方式生成小数序列。
for i in range(3)
print(i)
SyntaxError: expected ':'
原因:for 那一行结尾漏了冒号。冒号、缩进是 for 语句的两个必备零件。
for i in range(3):
print(i)
IndentationError: expected an indented block after 'for' statement on line 1
原因:循环体没有缩进。缩进就是「告诉 Python 哪些代码属于循环」的符号,不能省。
for i in range(3):
print(i)
SyntaxError: invalid character ':' (U+FF1A)
原因:用了中文全角冒号。输入法在中文状态下容易打出全角的标点,切换成英文再打。
print('开始')
break
SyntaxError: 'break' outside loop
原因:break 只能写在循环里面。没有循环,它不知道该结束谁。
continue
SyntaxError: 'continue' not properly in loop
原因:同上,continue 也必须待在循环体内。
for i in range(3):
print(total)
NameError: name 'total' is not defined
原因:变量还没定义就用了。累加器的 total = 0 必须写在循环之前。
for i in range(3):
print('第' + i + '次')
TypeError: can only concatenate str (not "int") to str
原因:字符串不能直接和数字相加。要么 str(i) 转换,要么直接用 f-string:print(f'第{i}次')。
for i in rang(3):
print(i)
NameError: name 'rang' is not defined. Did you mean: 'range'?
原因:函数名拼错。较新的 Python 3 版本会直接猜出你想写的是 range,照它提示改就行。
while true:
print('hi')
NameError: name 'true' is not defined. Did you mean: 'True'?
原因:Python 里的真值必须大写 True。写成 true、TRUE 都不认。
n = input('输入一个数字:')
while n > 0:
print(n)
n = n - 1
TypeError: '>' not supported between instances of 'str' and 'int'
原因:input() 读进来的永远是字符串,字符串和数字比不了大小。改成 n = int(input('输入一个数字:'))。
n = 5
for i in range(len(n)):
print(i)
TypeError: object of type 'int' has no len()
原因:len() 只能量「一串东西」的长度,单个数字没有长度。想数到 5 就写 range(n)。
score = 90
if score >= 60:
Pass
NameError: name 'Pass' is not defined
原因:Python 严格区分大小写,pass 必须全小写。写成了 Pass,Python 就把它当成一个从没定义过的变量名去取值,于是报 NameError。
不算报错,但会让你疑惑
| 现象 | 真相 |
|---|---|
for i in range(5, 1): 什么都不打印,也不报错 | 起点比终点大,而步长是正的,一个数都取不到。倒着数要写 range(5, 0, -1)。 |
| 程序卡住、光标一直闪,不报错也不结束 | 死循环。按 Ctrl + C 中断,然后检查「改变量」那一步。或者检查 continue 是不是把改变量跳过了。 |
| 循环体缩进了 8 格,居然也能跑 | 0、1、2 正常打印。缩进格数不影响功能,只要同一层一致;但混用 Tab 和空格会报 TabError。 |
循环结束后 i 居然还能用,值是 2 | 循环变量不是局部变量,循环结束后它保留最后一圈的值。 |
加了 pass,可什么都没输出 | 正常的。pass 就是「什么都不做」,它不打印、不计算、也不跳过任何代码;想跳过本圈要用 continue。 |
嵌套循环里写了 break,外层还在继续 | break 只结束最近的一层循环,想跳出两层要在外层再加判断。 |
AI 助手小贴士|双重循环的执行顺序靠脑子演容易乱。让 AI 一步一步列轨迹表,看两遍就开窍了。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:一步一步列出下面这段双重循环每轮的循环变量取值和打印结果,用表格呈现,最后总结外层和内层各跑了多少次:<粘贴代码>
十四、随堂自测(12 题)
点击选项即可判分,选错的题会立刻展开解析。做完可以看到正确率和错题清单,也可以重新答题。
1执行 for i in range(1, 5): 时,i 依次取到哪些值?
- A.
1, 2, 3, 4, 5 - B.
0, 1, 2, 3, 4 - C.
1, 2, 3, 4 - D.
1, 2, 3
range 的终点不包含:起点 1 取得到,终点 5 取不到,所以是 1、2、3、4。想取到 5 必须写 range(1, 6)。2while 循环写完后程序一直转、停不下来,最可能漏掉了三要素里的哪一个?
- A. ① 起点(初始值)
- B. ② 条件
- C. ③ 变化(让变量靠近终点)
- D. 循环体的缩进
while 时先问自己:变量在哪一步变大或变小,最后一定会让条件不成立?3break 和 continue 的区别是什么?
- A.
break结束整个循环,continue只跳过本次、继续下一圈 - B.
break跳过本次,continue结束整个循环 - C. 两个完全一样,只是写法不同
- D.
break只能用在for里,continue只能用在while里
break 是「整个不干了」,continue 是「这一圈不算,接着下一圈」。两个在 for 和 while 里都能用。4程序卡在死循环里一直在转,怎么把它停下来?
- A. 按
F5重启 - B. 在运行窗口按
Ctrl + C - C. 不用管,它转一会儿会自己停下来
- D. 把变量名改掉
Ctrl + C 会强行中断,屏幕出现 KeyboardInterrupt。看到它说明循环已被你按停,接着去检查「改变量」那一步。5想依次打印列表里的每个水果,下面哪种写法最合适?
- A.
for i in range(len(fruits)): - B.
while fruits: - C.
for fruit in fruits: - D.
for fruit in range(fruits):
for 变量 in 列表,简单又不容易错。A 绕了一圈还容易越界;D 会报错,因为 range() 不收列表。6执行下面这段后 i 的值是多少?for i in range(3): pass
- A.
0 - B.
2 - C.
3 - D. 报错,循环变量在循环外不能用
range(3) 给出 0、1、2,最后一圈 i 是 2。循环变量在循环结束后仍然保留最后一圈的值,可以直接用。7写累加(把一串数加起来)时,循环开始前应该先把总和变量设成什么?
- A.
0 - B.
1 - C. 第一个元素的值
- D. 不用设,直接加
0,累乘才设 1。而且 total = 0 必须写在循环之前,写在循环里每圈都会被清零。8嵌套循环中,内层执行了 break 会发生什么?
- A. 两层循环都结束
- B. 只有外层结束
- C. 程序直接报错
- D. 内层结束,外层继续转下一圈
break 只管最近的一层——内层停下,外层照常继续转。想一次跳出两层,得在外层再加一个判断(或者用标志变量)。9打印三角形图形时,print('*', end='') 里的 end='' 起什么作用?
- A. 让这一行不换行,接着在同一行继续打印
- B. 把星号换成空字符串
- C. 让循环提前结束
- D. 给星号之间加空格
print() 默认结尾换行,把结尾换成空字符串就留在同一行继续打,一行拼完再用一句空的 print() 换行。10想「重复 10 次」却根本用不到那个序号,循环变量怎么写最合适?
- A.
for i in range(10): - B.
for x in range(10): - C.
for _ in range(10): - D.
for range(10):
_ 是约定俗成的「这个值我不要」,写出来别人一看就知道它不是重点。D 语法不对,少了一个变量名。11关于 pass,下面说法正确的是?
- A.
pass什么都不做,它后面的代码照样执行 - B.
pass会跳过这一圈剩下的代码 - C.
pass会结束整个循环 - D.
pass和continue完全一样,只是写法不同
pass 是空语句,只占位、不做任何事,后面的代码和这一圈剩下的代码都会照常执行。跳过本圈是 continue,结束整个循环是 break。12写 for i in range(3): 之后直接换行,循环体一行都没写,会报什么错?
- A.
SyntaxError: expected ':' - B.
NameError: name 'i' is not defined - C. 不报错,循环空转 3 次
- D.
IndentationError: expected an indented block after 'for' statement on line 1
pass 即可。