查看: 478|回复: 3

Python for循环遍历列表、字典、集合、元组实用技巧及for-el

[复制链接]
发表于 昨天 10:00 | 显示全部楼层 |阅读模式
Python 的 for 循环与 C/Java 的计数循环不同,它直接遍历可迭代对象中的每一个元素,底层基于迭代器协议:调用 iter() 获取迭代器,反复调用 next() 直到 StopIteration。这使得 for 循环天然适合处理列表、元组、字典、集合、字符串等容器类型。本文将汇总 for 循环遍历各种数据结构的实用技巧,并给出常见坑点和实战案例。
  1. # for循环基本语法
  2. for 变量 in 可迭代对象:
  3.     循环体
  4. else:  # 可选,循环正常结束时执行
  5.     else代码块
  6. # 示例:遍历列表
  7. fruits = ["苹果", "香蕉", "橘子"]
  8. for fruit in fruits:
  9.     print(f"我喜欢吃{fruit}")
  10. # 字符串也是可迭代对象
  11. for char in "Python":
  12.     print(char, end=' ')  # 输出: P y t h o n
  13. # 底层机制模拟
  14. iterator = iter(fruits)
  15. while True:
  16.     try:
  17.         fruit = next(iterator)
  18.         print(fruit)
  19.     except StopIteration:
  20.         break
复制代码

一、遍历列表
直接遍历最常用。需要索引时推荐用 enumerate(),而非 range(len())。注意:遍历时不要直接修改列表长度(增删元素),否则会导致漏删或无限循环。正确做法是遍历副本、用列表推导式创建新列表,或者反向遍历按索引删除。
  1. fruits = ["苹果", "香蕉", "橘子", "葡萄", "西瓜"]
  2. # 基础遍历
  3. for fruit in fruits:
  4.     print(fruit)
  5. # 带索引遍历(推荐)
  6. for i, fruit in enumerate(fruits, start=1):
  7.     print(f"第{i}个: {fruit}")
  8. # 遍历时删除的正确方式:遍历副本
  9. numbers = [1, 2, 3, 4, 5]
  10. for n in numbers[:]:  # 副本
  11.     if n % 2 == 0:
  12.         numbers.remove(n)
  13. # 或列表推导式
  14. numbers = [n for n in numbers if n % 2 != 0]
  15. # 或反向遍历删除
  16. for i in range(len(numbers)-1, -1, -1):
  17.     if numbers[i] % 2 == 0:
  18.         del numbers[i]
复制代码

二、遍历元组
与列表语法相同,但元组不可修改,遍历时不存在意外修改的问题,具有“安全优势”。当元组内包含子元组时,可直接在 for 中解包。
  1. colors = ("红色", "绿色", "蓝色", "黄色")
  2. for color in colors:
  3.     print(color)
  4. # 解包便利:一个学生元组包含姓名、数学成绩、英语成绩
  5. students = [("张三", 85, 92), ("李四", 78, 88), ("王五", 92, 95)]
  6. for name, math, english in students:
  7.     avg = (math + english) / 2
  8.     print(f"{name}: 数学{math}, 英语{english}, 平均{avg:.1f}")
  9. # 部分解包 + * 收集剩余元素
  10. data = [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]
  11. for first, second, *rest in data:
  12.     print(f"前两个: ({first}, {second}), 剩余: {rest}")
复制代码

三、遍历字典
字典有三种遍历方式:遍历键(默认)、遍历 dict.values()、遍历 dict.items()(最常用)。items() 返回视图对象,不是拷贝,内存友好。遍历时可在 for 循环中直接解包 key 和 value。
  1. user = {"name": "张三", "age": 25, "city": "北京"}
  2. # 方式1:遍历键
  3. for key in user:
  4.     print(key)
  5. # 方式2:遍历值
  6. for value in user.values():
  7.     print(value)
  8. # 方式3:遍历键值对(推荐)
  9. for key, value in user.items():
  10.     print(f"{key}: {value}")
  11. # 带索引遍历字典
  12. for i, (key, value) in enumerate(config.items(), 1):
  13.     print(f"{i}. {key} = {value}")
  14. # 筛选遍历:根据值类型处理
  15. for key, value in config.items():
  16.     if isinstance(value, bool):
  17.         print(f"布尔配置: {key} = {value}")
  18.     elif isinstance(value, int):
  19.         print(f"数值配置: {key} = {value}")
复制代码

性能考量:keys()、values()、items() 返回视图对象,不占额外内存。如果需要多次遍历,可以转为 list 以加速。实测 10 万键值的字典,遍历键值对与仅遍历键的时间差距不大(约 0.1~0.2s),按需选择即可。

四、遍历集合
集合遍历无序,因哈希表实现。元素自动去重,成员检查 O(1)。若需有序输出,用 sorted()。结合集合运算(差集、交集、对称差)可以在循环前过滤数据。
  1. fruits_set = {"苹果", "香蕉", "橘子", "葡萄"}
  2. for fruit in fruits_set:
  3.     print(fruit)  # 每次输出顺序可能不同
  4. # 有序遍历
  5. for fruit in sorted(fruits_set):
  6.     print(fruit)
  7. # 集合运算实例
  8. all_users = {"张三", "李四", "王五", "赵六", "钱七"}
  9. vip_users = {"张三", "赵六", "孙八"}
  10. banned_users = {"李四", "钱七"}
  11. active_vip = vip_users & all_users - banned_users
  12. for user in active_vip:
  13.     print(f"给VIP用户 {user} 发福利!")
复制代码

五、嵌套遍历与并行遍历
二维列表(矩阵)可用双层 for 循环遍历,也可用列表推导式扁平化。需要并行遍历多个等长序列时用 zip(),它按最短序列截断;需要按最长序列则用 itertools.zip_longest。
  1. matrix = [[1,2,3],[4,5,6],[7,8,9]]
  2. # 双层遍历
  3. for row in matrix:
  4.     for element in row:
  5.         print(element, end=' ')
  6.     print()
  7. # 带索引的遍历
  8. for i, row in enumerate(matrix):
  9.     for j, element in enumerate(row):
  10.         print(f"matrix[{i}][{j}] = {element}")
  11. # 并行遍历 zip
  12. names = ["张三","李四","王五"]
  13. ages = [25,30,28]
  14. for name, age in zip(names, ages):
  15.     print(f"{name} {age}岁")
  16. # 按最长序列遍历(填充 None)
  17. from itertools import zip_longest
  18. short = [1,2]
  19. long_list = [1,2,3,4]
  20. for a,b in zip_longest(short, long_list, fillvalue=0):
  21.     print(a, b)
复制代码

六、for-else 语句
else 块在循环正常结束(未遇到 break)时执行,非常适合做“查找后未找到”的默认处理。
  1. def find_user(users, target):
  2.     for user in users:
  3.         if user["name"] == target:
  4.             print(f"找到用户: {user}")
  5.             break
  6.     else:
  7.         print(f"没有找到名为 {target} 的用户")
  8.         return None
  9.     return user
复制代码

七、实战案例
以下两个类展示了 for 循环的综合运用。
  1. class ScoreAnalyzer:
  2.     """学生成绩分析,嵌套遍历字典与列表"""
  3.     def __init__(self, scores):
  4.         self.scores = scores  # {姓名: {科目: 分数}}
  5.     def get_student_average(self):
  6.         result = {}
  7.         for name, subjects in self.scores.items():
  8.             if subjects:
  9.                 avg = sum(subjects.values()) / len(subjects)
  10.                 result[name] = round(avg, 1)
  11.         return result
  12.     def get_subject_average(self):
  13.         subject_scores = {}
  14.         for name, subjects in self.scores.items():
  15.             for subject, score in subjects.items():
  16.                 subject_scores.setdefault(subject, []).append(score)
  17.         result = {}
  18.         for subject, scores in subject_scores.items():
  19.             result[subject] = round(sum(scores)/len(scores), 1)
  20.         return result
  21.     def get_top_students(self, n=3):
  22.         totals = [(name, sum(subjects.values()))
  23.                   for name, subjects in self.scores.items()]
  24.         totals.sort(key=lambda x: x[1], reverse=True)
  25.         return totals[:n]
  26.     def get_failing_students(self, pass_score=60):
  27.         failing = set()
  28.         for name, subjects in self.scores.items():
  29.             for score in subjects.values():
  30.                 if score < pass_score:
  31.                     failing.add(name)
  32.                     break
  33.         return failing
  34. # 测试数据
  35. scores = {
  36.     "张三": {"语文":85, "数学":92, "英语":78, "物理":88},
  37.     "李四": {"语文":90, "数学":58, "英语":95, "物理":72},
  38.     "王五": {"语文":76, "数学":85, "英语":82, "物理":90},
  39. }
  40. analyzer = ScoreAnalyzer(scores)
  41. analyzer.generate_report()  # 方法详见原文
复制代码
  1. class ShoppingCart:
  2.     """购物车,遍历 items 列表计算总价、打印小票"""
  3.     def __init__(self):
  4.         self.items = []  # (name, price, quantity)
  5.     def add_item(self, name, price, quantity=1):
  6.         for i, (item_name, _, item_qty) in enumerate(self.items):
  7.             if item_name == name:
  8.                 self.items[i] = (item_name, price, item_qty + quantity)
  9.                 return
  10.         self.items.append((name, price, quantity))
  11.     def total_price(self):
  12.         return sum(price * qty for _, price, qty in self.items)
  13.     def print_receipt(self):
  14.         print(f"{'商品':<20} {'单价':>8} {'数量':>6} {'小计':>8}")
  15.         print("-"*45)
  16.         for name, price, quantity in self.items:
  17.             subtotal = price * quantity
  18.             print(f"{name:<20} ¥{price:>7.2f} {quantity:>6} ¥{subtotal:>7.2f}")
  19.         total = self.total_price()
  20.         print(f"{'合计':<20} {'':>8} {sum(qty for _,_,qty in self.items):>6}件 ¥{total:>7.2f}")
复制代码

小结:for 循环遍历列表、元组、字典、集合,各有注意事项。遍历列表时建议用 enumerate 带索引,避免在循环中增删原列表;字典推荐用 items() 解包;集合遍历无序,可用 sorted() 固定顺序;for-else 提供优雅的未找到处理方案。掌握这些技巧能让代码更简洁、安全、高效。
回复

使用道具 举报

发表于 昨天 10:10 | 显示全部楼层

Re: Python for循环遍历列表、字典、集合、元组实用技巧及for-el

非常实用的总结!特别是遍历时修改列表的几种正确方式,以及字典 items() 视图的内存友好特性,平时容易忽略。想请教一下:用 `enumerate` 遍历字典时,把 `items()` 的结果直接解包到 `(key, value)` 里,性能上比先取键再通过键取值好很多吧?另外集合部分好像没写完,期待后续补充!
回复 支持 反对

使用道具 举报

发表于 昨天 10:10 | 显示全部楼层

Re: Python for循环遍历列表、字典、集合、元组实用技巧及for-el

谢谢分享,非常全面!关于遍历时修改列表的坑我之前也遇到过,用副本或列表推导式确实是最稳妥的。另外 for-else 平时用得少,但读配置文件时需要“如果循环正常结束则执行某操作”的场景还挺好用,楼主能再举一个实际例子吗?
回复 支持 反对

使用道具 举报

发表于 昨天 10:10 | 显示全部楼层

Re: Python for循环遍历列表、字典、集合、元组实用技巧及for-el

感谢分享,总结得非常全面!尤其是遍历时修改列表长度的注意事项和解包元组的 *rest 技巧,很实用。想请教一下,你提到 for 循环基本语法里有 else 子句,但正文没有展开,实际开发中 for-else 一般用在什么场景呢?比如是否适合处理查找失败或循环正常结束后的逻辑?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-14 15:05 , Processed in 0.026231 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部