什么时候应该使用 iteritem ()而不是 item () ?

在所有地方使用 items()而不是 iteritems()是合法的吗?为什么从 Python3中删除了 iteritems()?看起来是个很棒很有用的方法。这背后的原因是什么?

编辑: 为了澄清,我想知道以类似生成器的方式(一次一项,而不是全部进入内存)在字典上进行迭代的正确习惯用法是什么,这种方式兼容 Python 2和 Python 3?

264862 次浏览

取消 dict.iteritems是因为 dict.items现在做的事情 dict.iteritems在 python 2.x 中做,甚至通过使它成为一个 itemview稍微改进了一点。

在 Python 2.x-.items()中返回一个(key,value)对列表。在 Python 3.x 中,.items()现在是一个 itemview对象,它的行为不同——所以它需要在 已经上迭代,或者物化... ... 所以,在 Python 2.x 中 dict.items()需要 list(dict.items())

Python 2.7在密钥处理方面也有一些后端,比如 viewkeysviewitemsviewvalues方法,其中最有用的是 viewkeys,它的行为更像 set(这是 dict的特点)。

举个简单的例子:

common_keys = list(dict_a.viewkeys() & dict_b.viewkeys())

将提供一个常用键的列表,但是在 Python 3.x 中,只需使用 .keys()即可。

Python 3.x 通常被设计得更“懒惰”——比如 map现在实际上是 itertools.imapzipitertools.izip,等等。

正如 巨蟒2巨蟒3的字典文档会告诉您的那样,在 python2中,items返回一个列表,而 iteritems返回一个迭代器。

在 python3中,items返回一个 风景,它与迭代器几乎相同。

如果您正在使用 python 2,那么如果您正在处理大型字典,并且您所要做的只是迭代这些项(不一定要将它们复制到列表中) ,那么您可能需要使用 iteritems

正如@Wessie 指出的,在 Python 3.x 中,dict.iteritemsdict.iterkeysdict.itervalues(返回 Python 2.x 中的 迭代器)以及 dict.viewitemsdict.viewkeysdict.viewvalues(返回 Python 2.x 中的 查看物体)都被删除了

在 Python 2.x 中,dict.itemsdict.keysdict.values用来返回字典列表的 收到,现在在 Python 3.x 中返回 查看物体但是仍然不同于 迭代器

如果希望在 Python 3.x 中返回 迭代器,请使用 iter(dictview):

$ python3.3


>>> d = {'one':'1', 'two':'2'}
>>> type(d.items())
<class 'dict_items'>
>>>
>>> type(d.keys())
<class 'dict_keys'>
>>>
>>>
>>> ii = iter(d.items())
>>> type(ii)
<class 'dict_itemiterator'>
>>>
>>> ik = iter(d.keys())
>>> type(ik)
<class 'dict_keyiterator'>

在 Python 中,不能在所有位置都使用 items而不是 iteritems:

class C:
def __init__(self, a):
self.a = a
def __iter__(self):
return self.a.iteritems()


>>> c = C(dict(a=1, b=2, c=3))
>>> [v for v in c]
[('a', 1), ('c', 3), ('b', 2)]

如果你使用 items:

class D:
def __init__(self, a):
self.a = a
def __iter__(self):
return self.a.items()


>>> d = D(dict(a=1, b=2, c=3))
>>> [v for v in d]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __iter__ returned non-iterator of type 'list'

视图项目也是如此,它在 Python3中可用。

此外,由于 物品返回字典的 (key, value)对列表的副本,因此效率较低,除非您无论如何都想创建一个副本。

在 Python2中,最好使用 iteritems进行迭代。如果您决定升级到 Python3,那么 2to3工具可以用 items代替它。

六个库 有助于编写兼容 python 2.5 + 和 python 3的代码。它有一个 iteritem 方法,可以同时在 python2和3中工作。例如:

import six


d = dict( foo=1, bar=2 )


for k, v in six.iteritems(d):
print(k, v)

future.utils考虑到了 python2和 python3的兼容性。

# Python 2 and 3: option 3
from future.utils import iteritems
heights = {'man': 185,'lady': 165}
for (key, value) in iteritems(heights):
print(key,value)


>>> ('lady', 165)
>>> ('man', 185)

请看这个链接: https://python-future.org/compatible_idioms.html

如果出于某种原因,某人仍然需要这样做,并且不想使用兼容性库,一个简单的方法是创建一个顶级可调用程序,通过版本调用正确的版本:

from operator import methodcaller
try:
{}.viewitems()
except AttributeError:
# Py3, use items
viewitems = methodcaller('items')
else:
viewitems = methodcaller('viewitems')


mydict = {...}
for k, v in viewitems(mydict):
...

这将在2.7和3 + 上表现相同(不复制,总是获得一个实时视图)。您可以将对 view的所有引用从 view改为 iter,以支持2.7版本之前的 Python,尽管在某些情况下行为会有细微的差别(视图是 iter布莱尔s,但不是 iteraTors; 您可以在迭代器上调用 next,但不能调用非迭代器迭代器迭代器)。

但实际上:

  1. 此时 Py2是 EOL,因此只需编写 Py3,并且
  2. 如果您必须同时支持这两种方式,那么对于 Py2尽可能便携地编写(使用所有的 __future__导入,显式的 ub前缀作为文本与字节的字面值,使用 io.open代替 open,等等) ,并且对于不能直接便携地编写的小东西使用 2to3