📊 阅读时长:20分钟 | 关键词:Python循环、while、for、range、break、continue、推导式
引言:让代码"重复"起来
假设你需要打印 1 到 100 的所有数字。如果没有循环,你会怎么做?
print(1)print(2)print(3)# ... 写到天荒地老print(100)这太蠢了。程序的一大优势就是可以重复执行——循环就是做这件事的。
Python 提供了两种循环结构:while循环和for循环。它们各有适用场景:
| 循环类型 | 使用场景 | 语法特点 |
|---|---|---|
while | 不知道循环次数,依赖条件判断 | while 条件: |
for | 知道循环次数,遍历可迭代对象 | for 变量 in 可迭代对象: |
一、while 循环:条件驱动
1.1 基本语法
while判断条件:循环体只要条件为True,就重复执行循环体;条件变为False时,循环结束。
# 打印 1 到 100num=1whilenum<=100:print(num)num+=1# 每次循环 num 加 1,最终会让条件变为 False关键点:循环体中必须有让条件最终变为False的代码,否则就是死循环。
1.2 while True:无限循环
有时候你需要一个"永远运行"的循环,配合break在适当时机退出:
# 打印 1 到 100(用 while True 实现)num=1whileTrue:print(num)num+=1ifnum>100:break# 满足条件时跳出循环while True的典型应用场景:
# 1. 持续接收用户输入whileTrue:name=input('请输入姓名(输入 q 退出):')ifname=='q':breakprint(f'你好,{name}!')# 2. 游戏主循环whileTrue:# 游戏逻辑...play_again=input('再来一局?(y/n):')ifplay_again!='y':break1.3 while 循环嵌套
循环里面可以再写循环——最经典的例子是九九乘法表:
# 用 while 实现九九乘法表right=1whileright<=9:left=1whileleft<=right:print(f'{left}×{right}={left*right}',end='\t')left+=1print()# 换行right+=1# 输出:# 1×1=1# 1×2=2 2×2=4# 1×3=3 2×3=6 3×3=9# ...# 1×9=9 2×9=18 3×9=27 ... 9×9=81理解嵌套循环:外层循环控制"行",内层循环控制"列"。外层每执行一次,内层完整执行一轮。
二、for 循环:遍历驱动
2.1 基本语法
for变量in可迭代对象:循环体for循环会逐个取出可迭代对象中的元素,赋值给变量,然后执行循环体。取完所有元素后自动停止。
lst=['d','c','k','a']# 遍历元素foriteminlst:print(item)# 输出:d c k a# 类比 while 的写法:# i = 0# while i < len(lst):# item = lst[i]# print(item)# i += 12.2 获取索引:range() 和 enumerate()
光有元素不够,很多时候你还需要知道元素的位置(索引)。
方式一:range() + len()
lst=['d','c','k','a']foriinrange(len(lst)):print(f'索引{i}:{lst[i]}')# 输出:# 索引 0:d# 索引 1:c# 索引 2:k# 索引 3:a方式二:enumerate()(推荐!)
lst=['d','c','k','a']forindex,iteminenumerate(lst):print(f'索引{index}:{item}')# 指定起始索引forindex,iteminenumerate(lst,start=1):print(f'第{index}个:{item}')# 输出:# 第 1 个:d# 第 2 个:c# 第 3 个:k# 第 4 个:a2.3 range() 详解
range()是for循环最常用的搭档。它的完整语法:
range(start,stop,step)# start:起始值(包含),默认 0# stop:结束值(不包含)# step:步长,默认 1# 只有一个参数:range(stop)print(list(range(4)))# [0, 1, 2, 3]# 两个参数:range(start, stop)print(list(range(1,5)))# [1, 2, 3, 4]# 三个参数:range(start, stop, step)print(list(range(1,8,2)))# [1, 3, 5, 7]# 负步长:倒序print(list(range(8,1,-2)))# [8, 6, 4, 2]# range 不是列表,是一个不可变的序列对象rg=range(1,8,2)print(len(rg))# 4print(rg[2])# 5 —— 支持索引print(rg[::2])# range(1, 9, 4) —— 支持切片print(5inrg)# True —— 支持成员检查range() 的优势:它不会一次性在内存中生成所有数字,而是"用到的时候才生成",所以range(100000000)也几乎不占内存。
2.4 for 循环嵌套
# 用 for 实现九九乘法表(比 while 更简洁)forrightinrange(1,10):forleftinrange(1,right+1):print(f'{left}×{right}={left*right}',end='\t')print()三、循环控制语句:break 和 continue
3.1 break:终止循环
break会立即终止所在的循环,程序跳到循环后面的代码继续执行。
# 找到第一个能被 7 整除的数fornuminrange(1,100):ifnum%7==0:print(f'找到了:{num}')break# 输出:找到了:7# break 只跳出所在的最近一层循环foriinrange(3):forjinrange(4):print(f'({i},{j})')break# 只跳出内层 for j 循环,外层 for i 继续# 输出:# (0, 0)# (1, 0)# (2, 0)3.2 continue:跳过本次循环
continue会跳过本次循环的剩余代码,直接进入下一次循环。
# 只打印奇数fornuminrange(1,11):ifnum%2==0:continue# 偶数跳过,不执行后面的 printprint(num)# 输出:1 3 5 7 93.3 break vs continue 对比
# break:终止循环foriinrange(1,6):ifi==3:breakprint(i)# 输出:1 2# continue:跳过本次foriinrange(1,6):ifi==3:continueprint(i)# 输出:1 2 4 53.4 for…else 和 while…else
Python 有一个独特的语法:循环后面可以跟else,当循环正常结束(没有被break中断)时执行:
# 循环正常结束,执行 elseforiinrange(3):print(i)else:print('循环正常结束')# 输出:# 0# 1# 2# 循环正常结束# 被 break 中断,不执行 elseforiinrange(5):ifi==3:breakprint(i)else:print('这行不会被执行')# 输出:0 1 2实用场景:查找元素,找不到时做处理:
# 查找列表中是否有负数nums=[1,3,5,7,9]fornuminnums:ifnum<0:print('找到了负数')breakelse:print('没有负数')# 循环正常结束才会执行四、推导式:一行代码替代循环
推导式是 Python 最受欢迎的特性之一。它让你用一行代码完成"遍历 + 过滤 + 转换"。
4.1 列表推导式
# 格式:[表达式 for 变量 in 可迭代对象 if 条件]# 基础:生成平方数列表squares=[x**2forxinrange(10)]# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]# 等价于传统写法:squares=[]forxinrange(10):squares.append(x**2)# 加过滤:只保留偶数的平方even_squares=[x**2forxinrange(10)ifx%2==0]# [0, 4, 16, 36, 64]# 加嵌套循环points=[(x,y)forxinrange(3)foryinrange(2)]# [(0,0), (0,1), (1,0), (1,1), (2,0), (2,1)]# 等价于传统写法:points=[]forxinrange(3):foryinrange(2):points.append((x,y))4.2 字典推导式
# 格式:{键: 值 for 变量 in 可迭代对象 if 条件}# 基础:数字到平方的映射d={x:x**2forxinrange(5)}# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}# 等价于传统写法:d={}forxinrange(5):d[x]=x**2# 反转键值对original={'a':1,'b':2,'c':3}reversed_dict={v:kfork,vinoriginal.items()}# {1: 'a', 2: 'b', 3: 'c'}4.3 集合推导式
# 格式:{表达式 for 变量 in 可迭代对象 if 条件}# 生成平方数集合(自动去重)s={x**2forxinrange(-3,4)}# {0, 1, 4, 9} —— 注意 1 和 4 出现了两次,但集合只保留一个# 等价于传统写法:s=set()forxinrange(-3,4):s.add(x**2)4.4 推导式 vs 传统循环:什么时候用哪个?
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 简单的"转换+过滤" | 推导式 | 一行搞定,清晰优雅 |
| 复杂的多步操作 | 传统循环 | 推导式太复杂反而难读 |
| 有副作用(如打印) | 传统循环 | 推导式不适合有副作用的操作 |
| 多层嵌套 | 传统循环或拆分为多步 | 嵌套推导式难以理解 |
# ✅ 适合推导式names=[user.nameforuserinusersifuser.is_active]# ❌ 不适合推导式(逻辑太复杂)result=[]foruserinusers:ifuser.is_active:data=fetch_data(user.id)ifdataanddata.score>60:result.append(process(data))五、动手练习
练习 1:打印图形
# 用循环打印以下图形:# *# **# ***# ****# *****foriinrange(1,6):print('*'*i)练习 2:FizzBuzz 经典面试题
# 打印 1 到 100:# 能被 3 整除 → 'Fizz'# 能被 5 整除 → 'Buzz'# 能同时被 3 和 5 整除 → 'FizzBuzz'# 其他 → 数字本身fornuminrange(1,101):ifnum%3==0andnum%5==0:print('FizzBuzz')elifnum%3==0:print('Fizz')elifnum%5==0:print('Buzz')else:print(num)练习 3:列表去重(不用 set)
# 给定一个列表,去除重复元素,保持原有顺序nums=[3,1,4,1,5,9,2,6,5,3,5]result=[]forxinnums:ifxnotinresult:result.append(x)print(result)# [3, 1, 4, 5, 9, 2, 6]小结
循环是编程中最基础也最重要的概念之一。核心要点:
| 知识点 | 关键内容 |
|:—|:—|:—|
| while | 条件驱动,适合不确定循环次数的场景 |
| for | 遍历驱动,适合已知可迭代对象的场景 |
| range() | 生成整数序列,range(start, stop, step),左闭右开 |
| enumerate() | 同时获取索引和元素 |
| break | 终止所在的最近一层循环 |
| continue | 跳过本次循环,进入下一次 |
| for…else | 循环正常结束(未被 break 中断)时执行 |
| 推导式 | 一行代码替代循环,适合简单的转换+过滤 |
下一篇文章,我们将进入 Python 编程中最重要的概念之一:函数——如何定义函数、参数传递的奥秘、return 返回值、以及作用域与命名空间。
本文是「Python从入门到数据分析」系列的第 6 篇,共 24 篇。关注我,不错过后续更新。