Python中for循环遍历列表元组字典集合的实用技巧
作者:星河耀银海
本文将手把手教你掌握Python中for循环的核心技巧,从列表、元组到字典、集合,甚至嵌套遍历和for-else语句,让你轻松应对90%以上的循环场景,写出简洁高效的Python代码
一、开篇:Python中最常用的循环
如果说while循环是"条件驱动"的循环,那么for循环就是"数据驱动"的循环——它天然适合遍历集合中的每一个元素。在Python中,for循环是绝对的主力循环结构,你在日常编码中90%以上的循环都是for循环。
for循环在Python中的设计哲学与众不同:
# Python的for循环——遍历可迭代对象中的每一个元素
fruits = ["苹果", "香蕉", "橘子"]
for fruit in fruits:
print(fruit)
# 不是其他语言中那种"计数器for循环"
# for (int i = 0; i < 10; i++) { ... } ← 这是C/Java的写法
# Python用 for i in range(10): 替代
Python的for循环之所以强大,是因为它建立在迭代器协议之上——几乎所有的容器类型(列表、元组、字典、集合、字符串)都是可迭代的,都可以被for循环直接遍历。今天我们就来全面掌握for循环遍历各种数据结构的技巧。
二、for循环的基本结构
2.1 基本语法
# for循环的基本语法
# for 变量 in 可迭代对象:
# 循环体
# else: # 可选
# else代码块
# 最简单的例子
fruits = ["苹果", "香蕉", "橘子", "葡萄", "西瓜"]
for fruit in fruits:
print(f"我喜欢吃{fruit}")
# 输出:
# 我喜欢吃苹果
# 我喜欢吃香蕉
# 我喜欢吃橘子
# 我喜欢吃葡萄
# 我喜欢吃西瓜
# 遍历字符串(字符串也是可迭代对象)
for char in "Python":
print(char, end=' ')
# 输出: P y t h o n
2.2 for循环的本质
# for循环的底层机制:
# 1. 调用 iter(可迭代对象) 获取迭代器
# 2. 反复调用 next(迭代器) 获取下一个值
# 3. 遇到 StopIteration 异常时停止
# 手动模拟for循环的执行过程
fruits = ["苹果", "香蕉", "橘子"]
# for fruit in fruits 等价于:
iterator = iter(fruits)
while True:
try:
fruit = next(iterator)
print(fruit)
except StopIteration:
break
# 了解这个机制很重要,因为它解释了:
# - 为什么for可以遍历任何实现了__iter__的对象
# - 为什么可以在遍历时获取下一个元素(迭代器是有状态的)
# - 为什么生成器可以和for循环无缝配合
2.3 for循环中修改变量不影响原数据
# 在for循环中修改循环变量,不会影响迭代过程
# 因为每次迭代都是从迭代器中获取下一个值
numbers = [1, 2, 3, 4, 5]
for n in numbers:
print(f"当前: {n}", end=' → ')
n = n * 10 # 修改循环变量
print(f"修改后: {n}")
print(f"\n原列表不变: {numbers}") # [1, 2, 3, 4, 5]
# 如果你想修改原列表的元素,需要通过索引
for i in range(len(numbers)):
numbers[i] = numbers[i] * 10
print(f"通过索引修改: {numbers}") # [10, 20, 30, 40, 50]
三、遍历列表
3.1 基础遍历
# 直接遍历列表元素(最常用)
fruits = ["苹果", "香蕉", "橘子", "葡萄"]
for fruit in fruits:
print(fruit)
# 遍历 + 条件判断
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = []
for n in numbers:
if n % 2 == 0:
even_numbers.append(n)
print(f"偶数: {even_numbers}")
# 遍历 + 累积
total = 0
for price in [19.9, 29.9, 39.9, 49.9]:
total += price
print(f"总价: {total:.1f}")
3.2 需要索引的遍历方式
fruits = ["苹果", "香蕉", "橘子", "葡萄", "西瓜"]
# 方式1:使用range(len()) —— C风格,不推荐
for i in range(len(fruits)):
print(f"{i}: {fruits[i]}")
# 方式2:使用enumerate() —— 推荐!✅
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
# 方式3:指定起始索引
for i, fruit in enumerate(fruits, start=1):
print(f"第{i}个: {fruit}")
# enumerate的实际应用:同时需要值和位置
def find_all_occurrences(items, target):
"""找到所有匹配项的索引"""
return [i for i, item in enumerate(items) if item == target]
data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
print(find_all_occurrences(data, 5)) # [4, 8, 10]
3.3 遍历时修改列表
# ⚠️ 重要:遍历列表时不要直接修改列表长度!
# 这会导致不可预期的行为
# ❌ 错误示例:遍历时删除元素
# numbers = [1, 2, 3, 4, 5]
# for n in numbers:
# if n % 2 == 0:
# numbers.remove(n) # 危险!
# print(numbers) # [1, 3, 5] —— 碰巧对了,但不能依赖
# # 实际上如果连续两个偶数,会漏删第二个!
# ❌ 错误示例:遍历时添加元素 → 无限循环!
# for n in numbers:
# numbers.append(n * 10) # 永远不会结束!
# ✅ 正确方式1:遍历副本
numbers = [1, 2, 3, 4, 5]
for n in numbers[:]: # numbers[:] 创建了副本
if n % 2 == 0:
numbers.remove(n)
print(numbers) # [1, 3, 5]
# ✅ 正确方式2:列表推导式(创建新列表)
numbers = [1, 2, 3, 4, 5]
numbers = [n for n in numbers if n % 2 != 0]
print(numbers) # [1, 3, 5]
# ✅ 正确方式3:反向遍历删除(通过索引)
numbers = [1, 2, 3, 4, 5]
for i in range(len(numbers) - 1, -1, -1):
if numbers[i] % 2 == 0:
del numbers[i]
print(numbers) # [1, 3, 5]
四、遍历元组
4.1 基本遍历
# 遍历元组和遍历列表完全一样
colors = ("红色", "绿色", "蓝色", "黄色")
for color in colors:
print(color)
# 元组不可修改,所以不会遇到"遍历时修改"的问题
# 这是元组在循环中的一个"安全优势"
4.2 元组解包遍历
# 当元组中的元素也是元组时,解包非常方便
coordinates = [(1, 2), (3, 4), (5, 6), (7, 8)]
# 直接在for循环中解包
for x, y in coordinates:
print(f"坐标: ({x}, {y}), 距离原点: {(x**2 + y**2)**0.5:.2f}")
# 三层解包
students = [
("张三", 85, 92),
("李四", 78, 88),
("王五", 92, 95),
]
for name, math, english in students:
avg = (math + english) / 2
print(f"{name}: 数学{math}, 英语{english}, 平均{avg:.1f}")
# 部分解包 + * 收集
data = [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]
for first, second, *rest in data:
print(f"前两个: ({first}, {second}), 剩余: {rest}")
五、遍历字典
5.1 字典遍历的三种方式
user = {
"name": "张三",
"age": 25,
"city": "北京",
"email": "zhangsan@example.com",
"phone": "13800138000",
}
# 方式1:遍历键(默认)
print("=== 遍历键 ===")
for key in user: # 等价于 for key in user.keys()
print(f" {key}")
# 方式2:遍历值
print("\n=== 遍历值 ===")
for value in user.values():
print(f" {value}")
# 方式3:遍历键值对(最常用)
print("\n=== 遍历键值对 ===")
for key, value in user.items():
print(f" {key}: {value}")
5.2 items()解包遍历
# items()返回的是dict_items视图对象
# 每个元素是一个(key, value)元组
# 在for循环中可以直接解包
config = {
"host": "localhost",
"port": 8080,
"debug": True,
"timeout": 30,
}
# 解包遍历(推荐写法)
for key, value in config.items():
print(f"{key:12} = {value}")
# 如果要同时获取索引
for i, (key, value) in enumerate(config.items()):
print(f"{i}: {key} = {value}")
# 筛选遍历
for key, value in config.items():
if isinstance(value, bool):
print(f"布尔配置: {key} = {value}")
elif isinstance(value, int):
print(f"数值配置: {key} = {value}")
5.3 字典遍历的性能考量
# 大数据量时,选择合适的遍历方式
import timeit
# 构建大字典
large_dict = {i: i**2 for i in range(100000)}
# 只遍历键
t_keys = timeit.timeit(lambda: [k for k in large_dict], number=100)
print(f"遍历键: {t_keys:.3f}s")
# 遍历键值对
t_items = timeit.timeit(lambda: [(k, v) for k, v in large_dict.items()], number=100)
print(f"遍历键值对: {t_items:.3f}s")
# 遍历值
t_values = timeit.timeit(lambda: [v for v in large_dict.values()], number=100)
print(f"遍历值: {t_values:.3f}s")
# 📝 注意:
# - keys()、values()、items() 返回的是视图对象,不是拷贝
# - 遍历时不会额外占用大量内存
# - 但如果要多次遍历,可以先转为list
六、遍历集合
6.1 基本遍历
# 集合的遍历——无序但高效
fruits = {"苹果", "香蕉", "橘子", "葡萄"}
for fruit in fruits:
print(fruit)
# 输出顺序不固定!
# 如果需要有序遍历,用sorted()
for fruit in sorted(fruits):
print(fruit)
# 现在按字母/拼音顺序输出
# 集合遍历的特点:
# 1. 每个元素只出现一次(重复自动去除)
# 2. 顺序不确定(哈希表实现)
# 3. O(1) 的成员检查(比列表O(n)快得多)
6.2 集合运算在循环中的应用
# 集合运算配合循环
all_users = {"张三", "李四", "王五", "赵六", "钱七"}
vip_users = {"张三", "赵六", "孙八"}
banned_users = {"李四", "钱七"}
# 找出所有正常用户
normal_users = all_users - banned_users
print(f"正常用户: {normal_users}")
# 找出VIP中的正常用户(VIP且未被封禁)
active_vip = vip_users & all_users - banned_users
print(f"活跃VIP: {active_vip}")
# 逐个处理
for user in active_vip:
print(f" 给VIP用户 {user} 发福利!")
# 遍历两个集合的对称差
for user in all_users ^ vip_users:
print(f" {user} 不是VIP或者是VIP但不在此列表")
七、嵌套遍历
7.1 二维数据的遍历
# 遍历二维列表(矩阵)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
# 方式1:双层for循环
print("双层for循环:")
for row in matrix:
for element in row:
print(f" {element}", end=' ')
print() # 换行
# 方式2:带索引的遍历
print("\n带坐标:")
for i, row in enumerate(matrix):
for j, element in enumerate(row):
print(f" matrix[{i}][{j}] = {element}")
# 方式3:列表推导扁平化
flat = [element for row in matrix for element in row]
print(f"\n扁平化: {flat}")
# 方式4:计算每行每列的和
row_sums = [sum(row) for row in matrix]
col_sums = [sum(row[i] for row in matrix) for i in range(len(matrix[0]))]
print(f"行和: {row_sums}")
print(f"列和: {col_sums}")
7.2 多列表并行遍历 (zip)
# zip() 并行遍历多个序列
names = ["张三", "李四", "王五", "赵六"]
ages = [25, 30, 28, 22]
cities = ["北京", "上海", "广州", "深圳"]
# 方式1:zip遍历
print("=== zip 并行遍历 ===")
for name, age, city in zip(names, ages, cities):
print(f" {name}, {age}岁, {city}")
# 方式2:zip + enumerate
print("\n=== zip + enumerate ===")
for i, (name, age, city) in enumerate(zip(names, ages, cities), 1):
print(f" {i}. {name} - {age}岁 - {city}")
# ⚠️ zip按最短序列截断
short = [1, 2]
long_list = [1, 2, 3, 4, 5]
for a, b in zip(short, long_list):
print(f" {a}, {b}") # 只输出2对!
# 如果需要按最长序列,用itertools.zip_longest
from itertools import zip_longest
print("\n=== zip_longest ===")
for a, b in zip_longest(short, long_list, fillvalue=None):
print(f" {a}, {b}")
八、for-else语句
# for-else 和 while-else 语义相同
# else在循环正常结束(没有被break中断)时执行
# 经典用法:搜索
def find_user(users, target_name):
for user in users:
if user["name"] == target_name:
print(f"找到用户: {user}")
break
else:
print(f"没有找到名为 {target_name} 的用户")
return None
return user
users = [
{"name": "张三", "age": 25},
{"name": "李四", "age": 30},
{"name": "王五", "age": 28},
]
find_user(users, "李四") # 找到
find_user(users, "赵六") # 没找到
# 另一个例子:验证所有元素
def all_positive(numbers):
for n in numbers:
if n <= 0:
print(f"发现非正数: {n}")
break
else:
print("所有数字都是正数")
return True
return False
print(all_positive([1, 2, 3, 4, 5])) # True
print(all_positive([1, -2, 3, 4])) # False
九、实战案例
9.1 学生成绩分析系统
class ScoreAnalyzer:
"""学生成绩分析 —— for循环遍历各种数据结构"""
def __init__(self, scores):
"""
scores格式: {
"张三": {"语文": 85, "数学": 92, "英语": 78},
"李四": {"语文": 90, "数学": 88, "英语": 95},
...
}
"""
self.scores = scores
def get_student_average(self):
"""计算每个学生的平均分"""
result = {}
for name, subjects in self.scores.items():
if subjects:
avg = sum(subjects.values()) / len(subjects)
result[name] = round(avg, 1)
return result
def get_subject_average(self):
"""计算每个科目的平均分"""
# 收集每个科目的所有分数
subject_scores = {}
for name, subjects in self.scores.items():
for subject, score in subjects.items():
if subject not in subject_scores:
subject_scores[subject] = []
subject_scores[subject].append(score)
# 计算平均
result = {}
for subject, scores in subject_scores.items():
result[subject] = round(sum(scores) / len(scores), 1)
return result
def get_top_students(self, n=3):
"""获取总分前N名的学生"""
totals = []
for name, subjects in self.scores.items():
total = sum(subjects.values())
totals.append((name, total))
# 按总分降序排列
totals.sort(key=lambda x: x[1], reverse=True)
return totals[:n]
def get_failing_students(self, pass_score=60):
"""获取有不及格科目的学生"""
failing = set()
for name, subjects in self.scores.items():
for subject, score in subjects.items():
if score < pass_score:
failing.add(name)
break
return failing
def generate_report(self):
"""生成成绩报告"""
print("=" * 50)
print("📊 成绩分析报告")
print("=" * 50)
# 学生平均分
print("\n📝 学生平均分:")
for name, avg in self.get_student_average().items():
bar = "█" * int(avg / 5)
print(f" {name:6} {avg:5.1f} {bar}")
# 科目平均分
print("\n📚 科目平均分:")
for subject, avg in self.get_subject_average().items():
print(f" {subject}: {avg}")
# 前3名
print("\n🏆 总分前三:")
for i, (name, total) in enumerate(self.get_top_students(3), 1):
print(f" {i}. {name}: {total}分")
# 不及格学生
failing = self.get_failing_students()
if failing:
print(f"\n⚠️ 有不及格科目的学生: {', '.join(failing)}")
else:
print(f"\n✅ 所有学生全部及格!")
# 测试数据
scores = {
"张三": {"语文": 85, "数学": 92, "英语": 78, "物理": 88},
"李四": {"语文": 90, "数学": 58, "英语": 95, "物理": 72},
"王五": {"语文": 76, "数学": 85, "英语": 82, "物理": 90},
"赵六": {"语文": 55, "数学": 72, "英语": 68, "物理": 45},
"钱七": {"语文": 92, "数学": 95, "英语": 90, "物理": 88},
}
analyzer = ScoreAnalyzer(scores)
analyzer.generate_report()
9.2 购物车结算系统
class ShoppingCart:
"""购物车 —— for循环遍历的综合应用"""
def __init__(self):
self.items = [] # [(name, price, quantity), ...]
def add_item(self, name, price, quantity=1):
# 检查是否已存在
for i, (item_name, item_price, item_qty) in enumerate(self.items):
if item_name == name:
self.items[i] = (item_name, item_price, item_qty + quantity)
return
self.items.append((name, price, quantity))
def remove_item(self, name):
self.items = [(n, p, q) for n, p, q in self.items if n != name]
def total_price(self):
return sum(price * qty for _, price, qty in self.items)
def item_count(self):
return sum(qty for _, _, qty in self.items)
def print_receipt(self):
"""打印小票"""
print("=" * 45)
print("🛒 购物清单")
print("=" * 45)
print(f"{'商品':<20} {'单价':>8} {'数量':>6} {'小计':>8}")
print("-" * 45)
for name, price, quantity in self.items:
subtotal = price * quantity
print(f"{name:<20} ¥{price:>7.2f} {quantity:>6} ¥{subtotal:>7.2f}")
print("-" * 45)
total = self.total_price()
count = self.item_count()
print(f"{'合计':<20} {'':>8} {count:>6}件 ¥{total:>7.2f}")
print("=" * 45)
# 使用
cart = ShoppingCart()
cart.add_item("Python编程书", 79.00, 2)
cart.add_item("机械键盘", 299.00, 1)
cart.add_item("鼠标垫", 29.90, 3)
cart.add_item("USB集线器", 49.00, 1)
cart.print_receipt()
十、本章小结
本文我们全面学习了Python for循环遍历各种数据结构:
- 基本结构:
for 变量 in 可迭代对象:,底层基于迭代器协议。 - 遍历列表:直接遍历、enumerate带索引遍历、遍历副本修改原列表。
- 遍历元组:和列表类似,但天然安全(不可修改)。元组的解包遍历非常强大。
- 遍历字典:三种方式——
for key in dict(键)、for value in dict.values()(值)、for k, v in dict.items()(键值对)。items()解包遍历最常用。 - 遍历集合:无序遍历,需要有序时用sorted()。配合集合运算做筛选非常高效。
- 嵌套遍历:双层for遍历二维数据、zip并行遍历多序列、zip_longest按最长序列遍历。
- for-else:和while-else语义一致——循环正常结束时执行else,被break中断时不执行。
for循环是Python中使用频率最高的循环结构。掌握它遍历各种数据类型的技巧,是写好Python代码的基础功。⌨️ 下一篇文章,我们将学习for-else循环的使用时机与注意点。
以上就是Python中for循环遍历列表元组字典集合的实用技巧的详细内容,更多关于Python for循环遍历的资料请关注脚本之家其它相关文章!
