news 2026/10/19 20:45:56

Python中for循环语句实战案例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python中for循环语句实战案例

前言


很多人从 C 或 Java 转过来,会先入为主地把for理解成「计数器循环」——初始化、判断、自增三段式。Python 的for完全不是这个模型。它的语义是遍历一个可迭代对象(iterable),把里面的元素一个一个取出来。range(10)看起来很像个计数器,其实它只是"可迭代对象"里最常见的一种。


这个理解差异会带来一批连锁误解:以为for循环变量有独立的块级作用域(其实泄漏到外层)、以为for一定要写range(len(x))(其实直接遍历元素更清晰)、以为range(1, 5)会包含 5(它是左闭右开)。


本文用一组实战案例把for的常见用法铺开:带序号遍历、同时遍历多个序列、遍历字典、for ... else做查找、嵌套循环里的break、以及反转与排序遍历。每个例子都能直接复制运行。


顺便说一句 Python 2:xrange这个名字在 Python 3 里已经被移除,因为range本身就是惰性的——它返回的是一个按需产生整数的对象,不会像 Python 2 的range那样一次性生成整个列表。同理,dict.iteritems()/iterkeys()/itervalues()也都没了,一律用.items()/.keys()/.values(),它们返回的是视图(view)而不再是列表。


一、for到底在遍历什么


for x in obj的执行过程只有两步:先调用iter(obj)拿到一个迭代器(iterator),然后反复对这个迭代器调用next(),直到抛出StopIteration。所以任何实现了__iter__的对象都能被for遍历——列表、元组、字符串、字典、集合、文件对象、生成器、range对象,全都是。


理解这一点,就能理解下面两件事:



  • 生成器只能遍历一次。第一次for把它消耗完了,第二次for什么都拿不到,因为它本身既是可迭代对象又是迭代器。

  • 遍历字典拿到的是键(key),不是键值对。要键值对得显式写.items()。




你想要的写法返回什么(Python 3)



遍历元素for x in seq元素本身

带序号for i, x in enumerate(seq)序号 + 元素

并行遍历多个for a, b in zip(s1, s2)各序列对应位置

遍历字典键for k in d键

遍历键值对for k, v in d.items()键、值

倒序遍历for x in reversed(seq)反序元素

排序后遍历for x in sorted(seq, key=...)排序后的元素

数字区间for i in range(a, b)整数,左闭右开



二、实战案例


案例一:带序号遍历


# 适用于 Python 3.8+
names = ["alice", "bob", "carol"]
for index, name in enumerate(names, start=1):
print(index, name)
# 1 alice / 2 bob / 3 carol

enumerate(iterable, start=0)的第二个参数是起点,默认从 0 开始。不要写for i in range(len(names)): name = names[i],那种写法既啰嗦又容易写错下标。


案例二:同时遍历两个序列


# 适用于 Python 3.8+
skus = ["A001", "A002", "A003"]
prices = [399, 129, 59]
for sku, price in zip(skus, prices):
print(sku, "=", price)

zip会在最短的序列耗尽时停止。也就是说skus有三个元素而prices只有两个时,第三个 sku 会被静默丢掉。如果这属于数据错误、你希望它报错,Python 3.10 起可以写zip(skus, prices, strict=True),长度不一致会抛ValueError。


案例三:遍历字典


# 适用于 Python 3.8+
# 3.7 起字典保证按插入顺序遍历
scores = {"math": 90, "english": 85, "history": 78}

for key in scores: # 等价于 scores.keys()
print("科目:", key)

for value in scores.values():
print("分数:", value)

for subject, score in scores.items():
print(subject, "->", score)

.keys()、.values()、.items()返回的都是视图,它们不是列表,会随字典内容动态变化。想固定下来要显式list(scores.items())。


案例四:for ... else做查找


# 适用于 Python 3.8+
names = ["alice", "bob", "carol"]
target = "dave"

for name in names:
if name == target:
print("找到了:", name)
break
else:
print("列表中没有", target)

else子句只在循环没有被break中断时执行。它天生适合表达"找遍了都没有"这种语义,比设一个found标志位再判断要干净。注意:如果循环体里有return,else也可能被执行——它是"没有 break",不是"没有提前退出"。


案例五:嵌套循环里的break


# 适用于 Python 3.8+
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
position = None

for row_index, row in enumerate(matrix):
for col_index, value in enumerate(row):
if value == 5:
position = (row_index, col_index)
break # 只跳出内层循环
if position is not None:
break # 外层需要再判断一次

print("5 的位置:", position) # (1, 1)

break只作用于它所在的那一层循环。要一次跳出多层,标准写法是把逻辑抽成函数用return直接返回,或者用for ... else配合标志位。Python 没有break 2这种带层数的语法。


案例六:反转、排序与区间


# 适用于 Python 3.8+
for ch in reversed("abc"):
print(ch) # c b a

for value in sorted([3, 1, 2], reverse=True):
print(value) # 3 2 1

for i in range(10, 0, -3):
print(i) # 10 7 4 1

reversed()要求对象要么是序列,要么实现了__reversed__。它不能反转任意迭代器,比如把一个生成器传进去会直接TypeError。sorted()返回新列表,原序列不动;如果原对象是列表且你想原地排序,用lst.sort()——注意它返回None,别写for x in lst.sort()。


常见坑点


1. 遍历列表的同时增删元素


❌


for item in nums:
if item % 2 == 0:
nums.remove(item) # 索引在变,会漏掉元素

✅


nums = [x for x in nums if x % 2 != 0]

一边走一边动,迭代器内部的索引和实际列表错位,结果是"删了一些但没删干净",且不报错。


2. 遍历字典时改它的大小


❌for k in d: d["new_" + k] = 1→RuntimeError: dictionary changed size during iteration✅for k in list(d): d["new_" + k] = 1先转成列表把键拷出来,再改原字典。改值(不改键集合)是允许的。


3. 以为range(1, 5)包含 5


❌list(range(1, 5))期待得到[1, 2, 3, 4, 5]✅ 它是左闭右开,实际是[1, 2, 3, 4],要含 5 得写range(1, 6)


4. 用range(len(x))取元素


❌


for i in range(len(names)):
print(names[i])

✅for name in names: print(name)只有确实需要下标时才用enumerate。range(len(...))既慢又容易越界。


5. 以为for循环变量只在循环内有效


❌ 在外层用同名变量,以为不会被覆盖 ✅ 要知道for不会创建新作用域,循环结束后变量保留最后一次的值


for i in range(3):
pass
print(i) # 2,i 仍然存在

6. 在闭包里引用循环变量


❌


funcs = [lambda: i for i in range(3)]
print([f() for f in funcs]) # [2, 2, 2],全是最后一个值

✅


funcs = [lambda i=i: i for i in range(3)]
print([f() for f in funcs]) # [0, 1, 2]

这是延迟绑定:闭包捕获的是变量本身,不是当时的值。


7. 用reversed()反转生成器


❌reversed(x for x in range(3))→TypeError: 'generator' object is not reversible✅ 先物化:reversed(list(x for x in range(3))),或用sorted(..., reverse=True)


8. 忽略zip的截断行为


❌ 拿两个长度不同的列表zip后直接当成一一对应 ✅ Python 3.10+ 用zip(a, b, strict=True)主动暴露长度不一致 静默截断会让"少的那部分数据"消失得无声无息。


总结




需求推荐写法要避开的写法



带序号enumerate(seq, start=1)range(len(seq))

并行遍历zip(a, b)用下标同时访问两个列表

键值对d.items()d.iteritems()(Python 2,已移除)

找不着就报错for...else手动设标志位

跳多层循环抽成函数用return层层设标志位

过滤重建列表推导式边遍历边remove



for在 Python 里是"遍历"而不是"计数",接受这个心智模型之后,绝大多数写法问题都会自然消失:不再需要下标、不再需要手写标志位、不再需要担心越界。真正需要盯住的,只剩下"不要在遍历过程中改变被遍历的对象"这一条。




版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 11:15:52

浙大开源nanoMuse轻量化视觉模型:本地部署与推理优化实战指南

1. 从标题拆解 nanoMuse 的核心定位1.1 这个项目到底在解决什么问题先把标题拆开看。“Muse”在近期的技术社区里被反复提及,通常指向一类具备较强生成与编辑能力的视觉内容模型,而“浙大开源版”和“nanoMuse”这两个词组合在一起,传递出的信…

作者头像 李华
网站建设 2026/10/19 5:29:42

设计院协同设计软件有哪些?信息中心主任的选型清单

导语:市面上自称『协同设计软件』的产品很多,但真正适合设计院的并不多。本文从勘察设计行业角度,帮你梳理设计院协同设计软件的主要类型,并给出信息中心主任可直接套用的选型清单。 一、先分清:协同设计软件大致分几类…

作者头像 李华
网站建设 2026/10/18 21:58:17

按摩浴缸服务商哪个靠谱?亲测复盘选型经验

去年帮一个精品民宿项目做卫浴采购,前后接触了六七家按摩浴缸服务商,踩过坑也攒了些经验。今天把选型过程复盘一下,重点聊聊怎么判断一家服务商是否靠谱。先说踩过的坑最开始图省事,找了一家号称"厂家直销"的贸易商。样…

作者头像 李华
网站建设 2026/10/18 14:29:55

AI音乐与虚拟艺人如何重塑2026音乐产业

1. 榜单现象解析:2026年3月11日Hot 100背后的音乐产业变革2026年3月11日这一期的Billboard Hot 100榜单呈现出几个显著特征:AI生成音乐首次占据榜单12%席位,虚拟艺人合作单曲包揽前三甲,而传统唱片公司发行的作品在Top 10中仅存3席…

作者头像 李华