What is the advantage of iteritems?
我使用的是带8GB内存和1.7GHz核心i5的python 2.7.5@mac os x 10.9.3。我测试了以下时间消耗。
1 2 3 4 5 6 7 8 9 | d = {i:i*2 for i in xrange(10**7*3)} #WARNING: it takes time and consumes a lot of RAM %time for k in d: k,d[k] CPU times: user 6.22 s, sys: 10.1 ms, total: 6.23 s Wall time: 6.23 s %time for k,v in d.iteritems(): k, v CPU times: user 7.67 s, sys: 27.1 ms, total: 7.7 s Wall time: 7.69 s |
似乎Iteritems比较慢。我想知道ITeritems与直接访问dict相比有什么优势。
更新:更准确的时间配置文件
1 2 3 4 5 | In [23]: %timeit -n 5 for k in d: v=d[k] 5 loops, best of 3: 2.32 s per loop In [24]: %timeit -n 5 for k,v in d.iteritems(): v 5 loops, best of 3: 2.33 s per loop |
为了回答您的问题,我们首先应该挖掘一些有关如何以及何时将
这与在python2.1中引入的
在python 2.3中,增加了
换言之,当时(而且现在)有一种强烈的行动懒散的趋势。其中一个原因是提高了内存效率。另一种方法是避免不必要的计算。
我找不到任何参考资料说它是为了提高查字典的速度而引入的。它只是用来替换对
例如,在代码中:
1 | function(dictionary.iteritems()) |
您不能像在示例中那样简单地使用
从
- 这不是懒惰,也就是说,在一个大的
dict 上打电话要花相当长的时间。 - 它需要大量的记忆。如果在一个很大的
dict 上调用一个程序,它几乎可以将该程序的内存使用量增加一倍,这个dict 包含被操作的大多数对象。 - 大多数情况下,它只迭代一次
所以,在介绍迭代器和生成器时,很明显只需要添加一个懒惰的对应项。如果您需要一个项目列表,因为您想索引它或多次迭代,请使用
使用
- 你写的代码更少,这使得它更干燥,减少了出错的机会。
- 代码更可读。
再加上懒散的优点。
正如我已经说过的,我不能复制您的性能结果。在我的机器上,
在平均性能相同的情况下,使用最易读、最简洁的选项:
我想指出的是,在Python体内,
这个版本比较懒惰(因此提供了
使用具有更多描述性名称的
与使用系统
1 2 3 4 5 6 7 | d = {i:i*2 for i in xrange(10**7*3)} #WARNING: it takes time and consumes a lot of RAM timeit for k in d: k, d[k] 1 loops, best of 3: 2.46 s per loop timeit for k, v in d.iteritems(): k, v 1 loops, best of 3: 1.92 s per loop |
我在windows上运行了这个,python 2.7.6。您是否多次运行它以确认系统本身没有发生什么问题?
从技术上讲,我知道这不是问题的答案,但是评论部分不适合放这类信息。我希望这能帮助人们更好地理解正在讨论的问题的本质。
为了彻底起见,我已经对一些不同的配置进行了计时。这些都是使用重复因子为
1 2 3 4 5 | python -m timeit -n 10 -s 'd={i:i*2 for i in xrange(10**7*3)}' 'for k in d: k, d[k]' >> 10 loops, best of 3: 2.05 sec per loop python -m timeit -n 10 -s 'd={i:i*2 for i in xrange(10**7*3)}' 'for k, v in d.iteritems(): k, v' >> 10 loops, best of 3: 1.74 sec per loop |
巴库鲁的建议
这个建议包括传入
1 2 3 4 5 | python -m timeit -n 10 -s 'd={i:i*2 for i in xrange(10**7*3)}' 'for k in d: v = d[k]' >> 10 loops, best of 3: 1.29 sec per loop python -m timeit -n 10 -s 'd={i:i*2 for i in xrange(10**7*3)}' 'for k, v in d.iteritems(): pass' >> 10 loops, best of 3: 934 msec per loop |
第一个任务没有分配
这个函数删除第一个循环中的赋值,但保持字典访问。这是不公平的比较,因为第二个循环创建了一个附加变量,并隐式地为其赋值。
1 2 | python -m timeit -n 10 -s 'd={i:i*2 for i in xrange(10**7*3)}' 'for k in d: d[k]' >> 10 loops, best of 3: 1.27 sec per loop |
有趣的是,分配对访问本身来说是微不足道的——差别仅仅是20毫秒。在每一个比较中(即使是最后的,不公平的),江户十一〔五〕都胜出。
在原始配置中,时间百分比最接近。这可能是由于大量工作正在创建一个元组(未在任何地方分配)。一旦从方程中去掉这一点,两种方法之间的差异就变得更加明显了。
dict.iter()在python 3.5中大获全胜。
下面是一个小的性能统计:
1 2 3 4 5 | d = {i:i*2 for i in range(10**3)} timeit.timeit('for k in d: k,d[k]', globals=globals()) 75.92739052970501 timeit.timeit('for k, v in d.items(): k,v', globals=globals()) 57.31370617801076 |