关于python:dict.items()和dict.iteritems()有什么区别?

What is the difference between dict.items() and dict.iteritems()?

dict.items()dict.iteritems()之间是否存在适用差异?

从python文档中:

dict.items(): Return a copy of the dictionary’s list of (key, value) pairs.

dict.iteritems(): Return an iterator over the dictionary’s (key, value) pairs.

如果我运行下面的代码,每个代码似乎都返回对同一对象的引用。我遗漏了什么细微的差异吗?

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/python

d={1:'one',2:'two',3:'three'}
print 'd.items():'
for k,v in d.items():
   if d[k] is v: print '\tthey are the same object'
   else: print '\tthey are different'

print 'd.iteritems():'  
for k,v in d.iteritems():
   if d[k] is v: print '\tthey are the same object'
   else: print '\tthey are different'

输出:

1
2
3
4
5
6
7
8
d.items():
    they are the same object
    they are the same object
    they are the same object
d.iteritems():
    they are the same object
    they are the same object
    they are the same object


这是进化的一部分。

最初,python items()构建了一个真正的元组列表,并返回了这个列表。这可能会占用大量的额外内存。

然后,一般将生成器引入该语言,并将该方法重新实现为名为iteritems()的迭代器生成器方法。原始版本保持向后兼容性。

python 3的一个变化是items()现在返回迭代器,并且列表从未完全构建。由于python 3中的items()与python 2.7中的viewitems()类似,因此iteritems()方法也不复存在。


dict.items()返回2个元组([(key, value), (key, value), ...]的列表),而dict.iteritems()是生成2个元组的生成器。前者最初占用更多的空间和时间,但访问每个元素的速度很快,而后者最初占用的空间和时间较少,但生成每个元素的时间稍长。


在Py2.x中

命令dict.items()dict.keys()dict.values()返回字典中(k, v)对、键和值列表的副本。如果复制的列表很大,这可能会占用大量内存。

命令dict.iteritems()dict.iterkeys()dict.itervalues()通过字典的(k, v)对、键和值返回一个迭代器。

命令dict.viewitems()dict.viewkeys()dict.viewvalues()返回视图对象,可以反映字典的变化。(例如,如果您在字典中添加一个项目或添加一个(k,v)对,则视图对象可以同时自动更改。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ python2.7

>>> d = {'one':1, 'two':2}
>>> type(d.items())
<type 'list'>
>>> type(d.keys())
<type 'list'>
>>>
>>>
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>
>>> type(d.iterkeys())
<type 'dictionary-keyiterator'>
>>>
>>>
>>> type(d.viewitems())
<type 'dict_items'>
>>> type(d.viewkeys())
<type 'dict_keys'>


而在Py3.x中

在py3.x中,情况更加干净,因为只有dict.items()dict.keys()dict.values()可用,它们返回视图对象,就像py2.x中的dict.viewitems()一样。

但是

正如@lvc所指出的,视图对象与迭代器不同,因此如果要在py3.x中返回迭代器,可以使用iter(dictview)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ 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'>

你问:"dict.items()和dict.iteritems()之间有什么适用的区别吗?"

这可能有帮助(对于python 2.x):

1
2
3
4
5
>>> d={1:'one',2:'two',3:'three'}
>>> type(d.items())
<type 'list'>
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>

可以看到,d.items()返回键、值对的元组列表,d.iteritems()返回字典项迭代器。

作为列表,d.items()可以切片:

1
2
3
>>> l1=d.items()[0]
>>> l1
(1, 'one')   # an unordered value!

但不会采用__iter__方法:

1
2
3
4
>>> next(d.items())
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
TypeError: list object is not an iterator

作为迭代器,d.ITeritems()不可切片:

1
2
3
4
>>> i1=d.iteritems()[0]
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
TypeError: 'dictionary-itemiterator' object is not subscriptable

但确实有__iter__

1
2
>>> next(d.iteritems())
(1, 'one')               # an unordered value!

所以项目本身是相同的——交付项目的容器是不同的。一个是列表,另一个是迭代器(取决于Python版本…)

因此dict.items()和dict.iteritems()之间的适用差异与列表和迭代器之间的适用差异相同。


dict.items()返回元组列表,dict.iteritems()返回字典中元组的迭代器对象为(key,value)。元组相同,但容器不同。

dict.items()基本上把所有字典都复制到列表中。尝试使用以下代码比较dict.items()dict.iteritems()的执行时间。你会看到区别。

1
2
3
4
5
6
7
8
9
10
11
12
import timeit

d = {i:i*2 for i in xrange(10000000)}  
start = timeit.default_timer() #more memory intensive
for key,value in d.items():
    tmp = key + value #do something like print
t1 = timeit.default_timer() - start

start = timeit.default_timer()
for key,value in d.iteritems(): #less memory intensive
    tmp = key + value
t2 = timeit.default_timer() - start

我的机器输出:

1
2
Time with d.items(): 9.04773592949
Time with d.iteritems(): 2.17707300186

这清楚地表明,dictionary.iteritems()的效率更高。


如果你有

dict = {key1:value1, key2:value2, key3:value3,...}

在python 2中,dict.items()复制每个元组,并返回字典中的元组列表,即[(key1,value1), (key2,value2), ...]。其含义是将整个字典复制到包含元组的新列表中

1
2
3
4
dict = {i: i * 2 for i in xrange(10000000)}  
# Slow and memory hungry.
for key, value in dict.items():
    print(key,":",value)

dict.iteritems()返回字典项迭代器。返回项的值也相同,即(key1,value1), (key2,value2), ...,但这不是列表。这只是字典项迭代器对象。这意味着更少的内存使用(减少50%)。

  • 作为可变快照列出:d.items() -> list(d.items())
  • 迭代器对象:d.iteritems() -> iter(d.items())

元组是相同的。你比较了每一个元组,这样你就得到了相同的结果。

1
2
3
4
dict = {i: i * 2 for i in xrange(10000000)}  
# More memory efficient.
for key, value in dict.iteritems():
    print(key,":",value)

在python 3中,dict.items()返回迭代器对象。dict.iteritems()已删除,因此不再有问题。


dict.iteritems在python3.x中消失了,因此使用iter(dict.iitems())获得相同的输出和内存分配


如果您想要迭代使用python 2和3的字典的项对,请尝试如下操作:

1
DICT_ITER_ITEMS = (lambda d: d.iteritems()) if hasattr(dict, 'iteritems') else (lambda d: iter(d.items()))

这样使用:

1
2
for key, value in DICT_ITER_ITEMS(myDict):
    # Do something with 'key' and/or 'value'.

dict.iteritems():给你一个迭代器。您可以在循环之外的其他模式中使用迭代器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
student = {"name":"Daniel","student_id": 2222}

for key,value in student.items():
    print(key,value)

('student_id', 2222)
('name', 'Daniel')

for key,value in student.iteritems():
    print(key,value)

('student_id', 2222)
('name', 'Daniel')

studentIterator = student.iteritems()

print(studentIterator.next())
('student_id', 2222)

print(studentIterator.next())
('name', 'Daniel')

python 2中的dict.iteritems()相当于python 3中的dict.items()。