for 循环
Python 的 for 循环不基于索引计数,而是直接遍历序列中的每个元素。这种设计让代码更简洁、更不容易出错——你不需要手动管理索引,也不需要担心越界。
基本语法
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print fruit
# 输出:
# apple
# banana
# cherry
for 后面跟变量名,in 后面跟可迭代对象,以冒号结尾。每次循环,变量被赋值为序列中的下一个元素,然后执行缩进块。
遍历字符串
字符串是可迭代对象,for 逐个字符遍历:
for char in "Hello":
print char
# 输出:
# H
# e
# l
# l
# o
遍历字典
遍历字典时,默认遍历键:
d = {"a": 1, "b": 2, "c": 3}
for key in d:
print key, d[key]
# 输出:
# a 1
# b 2
# c 3
也可以直接遍历键值对:
for key, value in d.items():
print key, value
注意 d.items() 返回列表(键值对元组的列表),d.iteritems() 返回迭代器(更省内存)。遍历大字典时推荐 iteritems():
for key, value in d.iteritems():
print key, value
遍历文件
文件对象是可迭代的,for 逐行读取:
with open("data.txt", "r") as f:
for line in f:
print line.strip()
这种方式内存效率高,因为每次只读取一行,而不是一次性加载整个文件。
for-else 子句
与 while 类似,for 也可以带 else 子句:
for n in [2, 4, 6, 8]:
if n % 2 != 0:
print "Found odd number"
break
else:
print "All numbers are even" # 执行,因为没有 break
else 在循环正常结束(没有被 break 打断)时执行。常用于搜索场景:
target = 7
for n in [2, 4, 6, 8]:
if n == target:
print "Found"
break
else:
print "Not found" # 执行,因为 7 不在列表中
同时修改序列的问题
在 for 循环中修改正在遍历的序列是危险的:
# 错误:删除列表中的偶数
nums = [1, 2, 3, 4, 5, 6]
for n in nums:
if n % 2 == 0:
nums.remove(n)
print nums # [1, 3, 5] —— 等等,真的对吗?
# 实际上:
nums = [1, 2, 3, 4, 5, 6]
for n in nums:
if n % 2 == 0:
nums.remove(n)
print nums # [1, 3, 5] —— 这次碰巧对了
# 但换个例子:
nums = [2, 2, 3, 4]
for n in nums:
if n % 2 == 0:
nums.remove(n)
print nums # [2, 3] —— 漏了一个 2!
原因是删除元素后,后续元素前移,但迭代器已经前进到下一个位置,导致跳过某些元素。正确做法是遍历副本:
nums = [2, 2, 3, 4]
for n in nums[:]: # 遍历副本
if n % 2 == 0:
nums.remove(n)
print nums # [3]
或者更 Pythonic 的写法:列表推导式创建新列表:
nums = [2, 2, 3, 4]
nums = [n for n in nums if n % 2 != 0]
print nums # [3]