iteritems有什么优势?

 詹建红_335 发布于 2023-01-09 15:22

我使用的是带有8GB内存和1.7GHz Core i5的Python 2.7.5 @ Mac OS X 10.9.3.我测试了时间消耗如下.

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有什么好处.

更新:获得更准确的时间配置文件

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

Bakuriu.. 15

要回答您的问题,我们应首先挖掘一些有关如何以及何时iteritems()添加到API的信息.

iteritems()在引入语言中的迭代器和生成器之后,在Python2.2中添加了该方法(另请参阅: dict.items()和dict.iteritems()之间有什么区别?).实际上,该方法在PEP 234中被明确提及.因此它被引入作为已经存在的惰性替代方案items().

这遵循file.xreadlines()file.readlines()Python 2.1中引入的相同的模式(顺便说一下,已经在python2.3中弃用).

在python 2.3 itertools模块,向其中加入引入懒惰同行map,filter

换句话说,当时(并且仍然存在)强烈倾向于操作的懒惰.其中一个原因是提高内存效率.另一个是避免不必要的计算.

我找不到任何引用说它是为了提高循环字典的速度而引入的.它只是用于替换items()实际上不必返回列表的调用.请注意,这包括更多用例而不仅仅是一个简单的for循环.

例如在代码中:

function(dictionary.iteritems())

你不能像在你的例子中那样简单地使用for循环替换iteritems().您必须编写一个函数(或使用genexp,即使它们在iteritems()引入时不可用,它们也不会干......).

从a中检索项目dict经常进行,因此提供内置方法确实有意义,事实上,有一个:items().问题items()是:

它不是懒惰的,这意味着在一个大的上面调用它dict可能需要相当长的时间

它需要大量的记忆.如果调用dict包含大多数被操作对象的非常大的程序,它几乎可以使程序的内存使用量翻倍

大多数情况下它只迭代一次

因此,在引入迭代器和生成器时,很明显只需添加一个惰性对应物.如果您需要一个项目列表,因为您想要对其进行索引或多次迭代,请使用items(),否则您可以使用iteritems()并避免上述问题.

使用的优点iteritems()与使用items()与手动获取值相同:

您编写的代码更少,这使得它更干,并减少出错的可能性

代码更具可读性.

加上懒惰的优点.


正如我已经说过的,我无法重现你的表现结果.在我的机器iteritems()总是比迭代+按键查找更快.无论如何,差异可以忽略不计,这可能是由于操作系统如何处理缓存和内存.换句话说,关于效率的论证并不是反对(也不赞成)使用一种或另一种替代方案的强烈论据.

鉴于平均性能相同,请使用最易读,最简洁的替代方案:iteritems().这个讨论类似于问"为什么当你可以通过索引以相同的性能循环时使用foreach?".foreach的重要性不在于您迭代速度更快,而是避免编写样板代码并提高可读性.


我想指出iteritems()实际上是在python3中删除了.这是该版本"清理"的一部分.Python3 items()方法id(大部分)等同于Python2的viewitems()方法(如果我没有弄错的话,实际上是一个backport ...).

这个版本是懒惰的(因此提供了替代iteritems())并且还具有进一步的功能,例如提供"类似集合"的操作(例如以dict有效的方式在s 之间查找公共项等等)所以在python3中使用的原因items()代替手动检索值更加引人注目.

4 个回答
  • 使用for k,v in d.iteritems()更具描述性的名称可以使循环套件中的代码更易于阅读.

    2023-01-09 15:23 回答
  • 而不是使用系统time命令,在ipython中运行,timeit产量为:

    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.你有多次运行它以确认它不是系统本身发生的事情吗?

    2023-01-09 15:24 回答
  • 要回答您的问题,我们应首先挖掘一些有关如何以及何时iteritems()添加到API的信息.

    iteritems()在引入语言中的迭代器和生成器之后,在Python2.2中添加了该方法(另请参阅: dict.items()和dict.iteritems()之间有什么区别?).实际上,该方法在PEP 234中被明确提及.因此它被引入作为已经存在的惰性替代方案items().

    这遵循file.xreadlines()file.readlines()Python 2.1中引入的相同的模式(顺便说一下,已经在python2.3中弃用).

    在python 2.3 itertools模块,向其中加入引入懒惰同行map,filter

    换句话说,当时(并且仍然存在)强烈倾向于操作的懒惰.其中一个原因是提高内存效率.另一个是避免不必要的计算.

    我找不到任何引用说它是为了提高循环字典的速度而引入的.它只是用于替换items()实际上不必返回列表的调用.请注意,这包括更多用例而不仅仅是一个简单的for循环.

    例如在代码中:

    function(dictionary.iteritems())
    

    你不能像在你的例子中那样简单地使用for循环替换iteritems().您必须编写一个函数(或使用genexp,即使它们在iteritems()引入时不可用,它们也不会干......).

    从a中检索项目dict经常进行,因此提供内置方法确实有意义,事实上,有一个:items().问题items()是:

    它不是懒惰的,这意味着在一个大的上面调用它dict可能需要相当长的时间

    它需要大量的记忆.如果调用dict包含大多数被操作对象的非常大的程序,它几乎可以使程序的内存使用量翻倍

    大多数情况下它只迭代一次

    因此,在引入迭代器和生成器时,很明显只需添加一个惰性对应物.如果您需要一个项目列表,因为您想要对其进行索引或多次迭代,请使用items(),否则您可以使用iteritems()并避免上述问题.

    使用的优点iteritems()与使用items()与手动获取值相同:

    您编写的代码更少,这使得它更干,并减少出错的可能性

    代码更具可读性.

    加上懒惰的优点.


    正如我已经说过的,我无法重现你的表现结果.在我的机器iteritems()总是比迭代+按键查找更快.无论如何,差异可以忽略不计,这可能是由于操作系统如何处理缓存和内存.换句话说,关于效率的论证并不是反对(也不赞成)使用一种或另一种替代方案的强烈论据.

    鉴于平均性能相同,请使用最易读,最简洁的替代方案:iteritems().这个讨论类似于问"为什么当你可以通过索引以相同的性能循环时使用foreach?".foreach的重要性不在于您迭代速度更快,而是避免编写样板代码并提高可读性.


    我想指出iteritems()实际上是在python3中删除了.这是该版本"清理"的一部分.Python3 items()方法id(大部分)等同于Python2的viewitems()方法(如果我没有弄错的话,实际上是一个backport ...).

    这个版本是懒惰的(因此提供了替代iteritems())并且还具有进一步的功能,例如提供"类似集合"的操作(例如以dict有效的方式在s 之间查找公共项等等)所以在python3中使用的原因items()代替手动检索值更加引人注目.

    2023-01-09 15:24 回答
  • 我从技术上知道这不是问题的答案,但评论部分是放置这类信息的不好的地方.我希望这有助于人们更好地理解所讨论问题的本质.

    为了彻底,我已经定时了一堆不同的配置.这些都是定时使用timeit的重复因子10.这是在Mac OS X 10.9.3上使用CPython 2.7.6版本,配备16GB内存和2.3GHz Core i7.

    原配置

    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
    

    Bakuriu的建议

    这个建议涉及传入iteritems循环,并v通过访问字典来为第一个循环中的变量赋值k.

    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
    

    第一个没有任务

    这个删除第一个循环中的赋值,但保持字典访问.这不是一个公平的比较,因为第二个循环创建了一个额外的变量并隐式赋值.

    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毫秒.在每次比较中(即使是最终的,不公平的iteritems比赛),胜出.

    在原始配置中,时间是最接近的百分比.这可能是由于大部分工作正在创建元组(未在任何地方分配).一旦将其从等式中移除,两种方法之间的差异就会变得更加明显.

    2023-01-09 15:25 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有