You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何分两步获取字典前30个键比一步操作更快?

为什么分两步获取字典前30个键更快?

这确实是个挺有意思的细节!让我们一步步拆解这三种实现的执行逻辑,搞清楚背后的原因:

首先先明确一个基础知识点:Python中dict.keys()返回的是字典视图对象(类型为dict_keys),它不是一个已经存储了所有键的列表,而是一个动态反映字典变化的可迭代对象——只有当你遍历它时,才会逐个取出字典中的键。

三种方法的执行流程

我们先回顾你的测试代码:

import time
dic = {str(i): i for i in range(10 ** 6)}

# 方法1
start_time = time.time()
x = list(dic.keys())[0:30]
print(time.time() - start_time)

# 方法2
start_time = time.time()
y = list(dic.keys())
x = y[0:30]
print(time.time() - start_time)

# 方法3
start_time = time.time()
z = dic.keys()
y = list(z)
x = y[0:30]
print(time.time() - start_time)

方法1:list(dic.keys())[0:30]

执行步骤:

  1. 调用list()遍历整个字典的100万个键,生成一个包含百万元素的完整列表(这是最耗时的步骤)。
  2. 对这个大列表执行切片[0:30],生成一个只包含前30个元素的小列表,赋值给x。
  3. 此时,那个百万元素的大列表是临时对象——没有任何变量引用它,Python的垃圾回收机制会很快标记它为待回收对象,并在该表达式执行完成后销毁它。而销毁这个大列表的内存开销,被算进了方法1的总耗时里。

方法2:y = list(dic.keys()); x = y[0:30]

执行步骤:

  1. 同样生成百万元素的完整列表,但这次把它赋值给了变量y,这个列表有了明确的引用。
  2. 对y执行切片生成小列表赋值给x。
  3. 由于y还被引用着,Python不会在这段测试时间内销毁它,因此垃圾回收的额外开销没有被计入方法2的耗时,这就是它比方法1快的核心原因。

方法3:z = dic.keys(); y = list(z); x = y[0:30]

和方法2的核心步骤一致,只是多了一步把字典视图赋值给z的操作。这一步虽然开销极小,但累积下来会让总耗时略高于方法2,和方法1的耗时接近。

更高效的优化方案

其实你的三种方法都做了没必要的工作:生成完整的百万元素列表。既然我们只需要前30个键,完全可以只遍历前30个元素,不需要处理剩下的999970个键。用itertools.islice就能实现:

import itertools
start_time = time.time()
x = list(itertools.islice(dic.keys(), 30))
print(time.time() - start_time)

这种方法的耗时会远低于你测试的三种方法,因为它只需要从字典视图中取出前30个键,直接生成小列表,完全跳过了遍历百万键的步骤。

内容的提问来源于stack exchange,提问作者Diamond

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:42:57