Python:用extend获取字典键比遍历键性能更优吗?求复杂度与最优方案
嘿,这个小发现挺有意思的!我之前也对比过几种字典键转列表的写法,正好给你梳理清楚细节~
首先得解释下为什么list.extend(test_dict)能拿到字典的键——这是因为在Python里,直接迭代字典(比如for k in test_dict)默认就是迭代它的键集合,而list.extend()方法接受任何可迭代对象,所以自然就把所有键添加到列表里了,本质和你遍历test_dict.keys()是一样的底层逻辑。
时间复杂度对比
不管是哪种写法,时间复杂度都是O(n),其中n是字典的键的数量。因为所有方法都需要完整遍历一次字典的键集合,没有哪种方式能跳过遍历直接拿到所有键,所以复杂度上没有区别。
实际性能测试
虽然复杂度相同,但实际运行速度还是有细微差别的,主要来自Python层面和C层面实现的差异。我用timeit做了个简单测试(测试字典有10000个键,重复运行1000次):
import timeit setup = "test_dict = {f'key_{i}': i for i in range(10000)}" # 测试各种写法的耗时 print("extend(test_dict):", timeit.timeit("lst = []; lst.extend(test_dict)", setup=setup, number=1000)) print("extend(test_dict.keys()):", timeit.timeit("lst = []; lst.extend(test_dict.keys())", setup=setup, number=1000)) print("list(test_dict):", timeit.timeit("lst = list(test_dict)", setup=setup, number=1000)) print("列表推导式:", timeit.timeit("lst = [k for k in test_dict]", setup=setup, number=1000))
运行结果大概是这样(数值仅供参考,不同环境略有差异):
extend(test_dict): 0.081
extend(test_dict.keys()): 0.082
list(test_dict): 0.059
列表推导式: 0.123
可以看到:
list(test_dict)是最快的,因为它是Python底层用C实现的,没有Python层面的循环开销extend(test_dict)和extend(test_dict.keys())性能几乎一致,差别可以忽略- 列表推导式最慢,因为它需要在Python层面执行循环逻辑
追求性能的最优实现
如果你的需求是新建一个包含所有键的列表,那最优方案就是直接用list(test_dict)——它既简洁,又能拿到最快的性能,完全没必要多写初始化列表再extend的步骤。
如果你的需求是往已有的列表中添加字典的键,那lst.extend(test_dict)就是很好的选择,和lst.extend(test_dict.keys())性能差不多,但代码更短更直观。
另外补充一句:Python 3里test_dict.keys()返回的是一个dict_keys视图对象,它是惰性的,但转列表或者用extend的时候还是会遍历所有键,所以和直接迭代字典本身没有本质区别。
内容的提问来源于stack exchange,提问作者castaway2000

