Python2 中的 dict.items() 和 dict.iteritems() 有啥区别?
Posted
技术标签:
【中文标题】Python2 中的 dict.items() 和 dict.iteritems() 有啥区别?【英文标题】:What is the difference between dict.items() and dict.iteritems() in Python2?Python2 中的 dict.items() 和 dict.iteritems() 有什么区别? 【发布时间】:2012-05-14 13:33:57 【问题描述】:dict.items()
和 dict.iteritems()
之间有什么适用的区别吗?
来自Python docs:
dict.items()
:返回字典的(键、值)对列表的副本。
dict.iteritems()
:在字典的(键,值)对上返回一个迭代器。
如果我运行下面的代码,每个似乎都返回对同一对象的引用。有没有我遗漏的细微差别?
#!/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'
输出:
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
【问题讨论】:
它们的计算方式基本上有所不同。items()
一次创建所有项目并返回一个列表。 iteritems()
返回一个生成器 - 生成器是一个对象,每次在其上调用 next()
时,它一次“创建”一个项目。
在您的特定情况下,d[k] is v
将始终返回 True,因为 python 为 -5 到 256 之间的所有整数保留一个整数对象数组:docs.python.org/2/c-api/int.html 当您在该范围内创建一个 int 时,您实际上只需取回对现有对象的引用:>> a = 2; b = 2 >> a is b True
但是,>> a = 1234567890; b = 1234567890 >> a is b False
@the_wolf 我认为最好添加您在问题中引用的文档的 python 版本。
在 Python 3 中 iteritems()
是否更改为 iter()
?上面的文档链接似乎与这个答案不匹配。
不完全是,@GabrielStaples。 iteritems() 从字典 Python 3 中删除,并且没有替代品。然而,为了同样的效果,你确实使用了 iter()。例如迭代(dict.items())。见鼓舞士气 469:python.org/dev/peps/pep-0469
【参考方案1】:
这是进化的一部分。
最初,Python items()
构建了一个真实的元组列表并将其返回。这可能会占用大量额外的内存。
然后,生成器被引入到语言中,并且该方法被重新实现为名为@987654324@ 的迭代器生成器方法。保留原件是为了向后兼容。
Python 3 的一个变化是 items()
现在返回视图,而 list
永远不会完全构建。 iteritems()
方法也消失了,因为 Python 3 中的 items()
与 Python 2.7 中的 viewitems()
一样工作。
【讨论】:
请注意,您错过了进化的一步:Py3 的行为与iteritems()
不同。它实际上创建了一个完整的序列协议对象,该对象也反映了对 dict 的更改(并且由 dict 本身支持,而不是冗余列表)- 它已被向后移植到 2.7,为 viewitems()
。
我想更详细地了解这一点,但我的 google-fu 让我失望了。有人可以向我指出可以帮助我更好地理解这一点的文档、文章或资源吗? @lvc?
@Stew 更改在PEP 3106 中进行了描述,what's new in python 3.0 中还有更多内容
抱歉详细说明了这个古老的问题,但我是否正确理解在 Python 2.x 中 iteritems()
总是优于 items()
?
@RubenGeert 大多数时候,这并不重要。对于非常大的字典,它可能更可取。【参考方案2】:
dict.iteritems
在 Python3.x 中消失了所以使用iter(dict.items())
来获得相同的输出和内存分配
【讨论】:
【参考方案3】:如果您想要一种方法来迭代适用于 Python 2 和 3 的字典的项目对,请尝试以下操作:
DICT_ITER_ITEMS = (lambda d: d.iteritems()) if hasattr(dict, 'iteritems') else (lambda d: iter(d.items()))
像这样使用它:
for key, value in DICT_ITER_ITEMS(myDict):
# Do something with 'key' and/or 'value'.
【讨论】:
【参考方案4】:dict.iteritems()
: 给你一个迭代器。您可以在循环之外的其他模式中使用迭代器。
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')
【讨论】:
【参考方案5】:python 2 中的 dict.iteritems() 等价于 python 3 中的 dict.items()。
【讨论】:
这是不正确的。之前的答案中已经解释了差异。【参考方案6】:dict.items()
返回元组列表,dict.iteritems()
返回字典中元组的迭代器对象为(key,value)
。元组相同,但容器不同。
dict.items()
基本上将所有字典复制到列表中。尝试使用以下代码比较dict.items()
和dict.iteritems()
的执行时间。你会看到不同的。
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
在我的机器上输出:
Time with d.items(): 9.04773592949
Time with d.iteritems(): 2.17707300186
这清楚地表明dictionary.iteritems()
效率更高。
【讨论】:
【参考方案7】:如果你有
dict = key1:value1, key2:value2, key3:value3,...
在 Python 2 中,dict.items()
复制每个元组并返回字典中的元组列表,即[(key1,value1), (key2,value2), ...]
。
这意味着整个字典被复制到包含元组的新列表中
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())
元组是相同的。你比较了每个元组,所以你得到了相同的结果。
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() 已被删除,因此不再有问题。
【讨论】:
【参考方案8】:在 Py2.x 中
命令dict.items()
、dict.keys()
和dict.values()
返回字典的list 的副本,其中包含(k, v)
对、键和值。
如果复制的列表非常大,这可能会占用大量内存。
命令dict.iteritems()
、dict.iterkeys()
和dict.itervalues()
在字典的(k, v)
对、键和值上返回一个迭代器。
命令dict.viewitems()
、dict.viewkeys()
和dict.viewvalues()
返回view objects,可以反映字典的变化。
(即,如果您 del
一个项目或在字典中添加 (k,v)
对,则视图对象可以自动同时更改。)
$ 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 中的 dict.viewitems()
。 x 做到了。
但是
正如@lvc 所说,view object 与 iterator 不同,所以如果你想在 Py3 中返回一个 iterator .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'>
【讨论】:
【参考方案9】:您问:'dict.items() 和 dict.iteritems() 之间是否有任何适用的区别'
这可能会有所帮助(对于 Python 2.x):
>>> d=1:'one',2:'two',3:'three'
>>> type(d.items())
<type 'list'>
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>
您可以看到d.items()
返回键、值对的元组列表,d.iteritems()
返回一个字典迭代器。
作为一个列表,d.items() 是可切片的:
>>> l1=d.items()[0]
>>> l1
(1, 'one') # an unordered value!
但不会有__iter__
方法:
>>> next(d.items())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator
作为一个迭代器,d.iteritems() 不是可切片的:
>>> i1=d.iteritems()[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'dictionary-itemiterator' object is not subscriptable
但确实有__iter__
:
>>> next(d.iteritems())
(1, 'one') # an unordered value!
所以物品本身是相同的——运送物品的容器是不同的。一个是列表,另一个是迭代器(取决于 Python 版本...)
所以 dict.items() 和 dict.iteritems() 之间的适用差异与列表和迭代器之间的适用差异相同。
【讨论】:
【参考方案10】:dict.items()
返回一个 2 元组列表 ([(key, value), (key, value), ...]
),而 dict.iteritems()
是产生 2 元组的生成器。前者最初需要更多的空间和时间,但访问每个元素的速度很快,而后者最初需要的空间和时间更少,但生成每个元素的时间要多一些。
【讨论】:
那么为什么每个元素都一样呢? 您为什么希望它们有所不同? 文档中的“复制”并不意味着元素被复制(如果需要,请使用copy.deepcopy
)。这意味着它是字典项的副本:如果您执行items = dct.items()
,然后通过添加/删除键或dct[k] = other_v
修改dct
,items
将保持不变。
除非明确说明,否则 Python 中的任何内容都不是深拷贝。
@IgnacioVazquez-Abrams - 关于“更多的空间和时间”:字典的大小开始变得重要。假设我有一个“大”字典1:'one', 2:'two', ...
,我想在网络服务器上迭代并呈现结果。我应该在多大程度上开始担心为 Python 2.7 选择 .items()
和 .iteritems()
?以上是关于Python2 中的 dict.items() 和 dict.iteritems() 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
Python 3字典迭代中的性能:dict [key] vs. dict.items()
some_dict.items()是Python中的迭代器吗?
some_dict.items() 是 Python 中的迭代器吗?