Python中遍历含固定键的字典列表的多种方法及优劣探讨
Python中遍历含固定键的字典列表的多种方法及优劣探讨
作为Python新手,我最近一直在琢磨同一件事的不同实现方式——就拿这个场景来说:我有一个由字典组成的列表,每个字典都固定有Key和Value两个键:
a = [ {"Key": "K1", "Value": "V1"}, {"Key": "K2", "Value": "V2"} ]
我想要遍历这个列表,每次循环都能拿到索引、Key值、Value值,最终输出这样的结果:
0 K1 V1 1 K2 V2
下面我整理了几种实现方式,顺便聊聊它们的优缺点:
1. 最直白的基础写法
这应该是最容易理解的写法,每一步都拆解得明明白白:
l = len(a) for i in range(l): d = a[i] k = d['Key'] v = d['Value'] print(i, k, v)
- 优点:完全无门槛,新手看一眼就懂,不需要记住任何Python特有的语法,每一步的逻辑都清晰可见。
- 缺点:太啰嗦了,重复的索引取值和字典取值写起来费时间,代码行数多,不够简洁。
2. 用enumerate简化的常规推荐写法
后来有人提醒我可以用enumerate,这才是Python开发者常用的常规写法:
for index, kvdict in enumerate(a): key, value = kvdict['Key'], kvdict['Value'] print(index, key, value)
(注:原代码里把kvdict误写为d,这里做了修正)
- 优点:比基础写法简洁很多,
enumerate直接帮我们拿到索引和对应的字典,不用手动计算长度和取索引;同时可读性依然很强,团队里的其他开发者一眼就能看懂。 - 缺点:还是需要单独一行(或半行)来取出字典里的Key和Value,没法在循环头里直接拿到三个变量。
3. 列表推导式预转换的紧凑写法
我自己折腾了半天,想出了这种用列表推导式配合enumerate的写法:
for i, k, v in [(i, o['Key'], o['Value']) for i, o in enumerate(a)]: print(i, k, v)
- 优点:循环头里直接拿到三个变量,循环体看起来非常干净紧凑,满足了“一行循环头”的需求。
- 缺点:效率问题很明显——列表推导式会先把整个原列表遍历一遍,生成一个包含所有元组的新列表。如果原列表非常大,会额外占用大量内存,完全没必要;而且可读性不如前两种,新手可能会困惑这个列表推导式的作用。
4. 生成器表达式优化版(解决内存问题)
如果想保留紧凑的循环头,又不想浪费内存,可以把列表推导式换成生成器表达式(把方括号改成圆括号):
for i, k, v in ((i, o['Key'], o['Value']) for i, o in enumerate(a)): print(i, k, v)
- 优点:和列表推导式写法几乎一样,但生成器是迭代时才逐个生成元素,不会一次性把所有数据加载到内存里,适合处理大列表;循环体依然保持简洁。
- 缺点:可读性还是比enumerate的常规写法稍差一点,需要理解生成器的概念才能明白为什么这么写。
5. 用map+lambda的“一行式”(不推荐)
还有一种更极致的一行式思路,用map配合lambda:
for i, k, v in map(lambda x: (x[0], x[1]['Key'], x[1]['Value']), enumerate(a)): print(i, k, v)
- 优点:确实做到了循环头的“一行式”转换。
- 缺点:可读性极差,
lambda里的x[0]、x[1]很容易让人混淆到底对应什么,后期维护起来很麻烦,除非团队所有人都熟悉这种写法,否则不建议用。
总结一下选择思路
- 如果追求可读性和易维护:优先选
enumerate的常规写法,这是Python社区的共识写法。 - 如果列表很小,想追求代码紧凑:可以用列表推导式的写法,但别在大列表上用。
- 如果列表很大又想保持紧凑:换成生成器表达式,兼顾简洁和内存效率。
- 基础写法适合新手理解原理,但实际项目里没必要用这么啰嗦的代码。
map+lambda的写法尽量避免,除非有特殊场景。
备注:内容来源于stack exchange,提问作者Jules




