如果我理解正确,在Python 2中,iter(d.keys())
与d.iterkeys()
相同。但是现在,d.keys()
是一个视图,位于列表和迭代器之间。视图和迭代器之间有什么区别?
换句话说,在Python 3中,
之间有什么区别for k in d.keys()
f(k)
和
for k in iter(d.keys())
f(k)
此外,这些差异如何在简单的for
循环中显示(如果有的话)?
答案 0 :(得分:63)
我不确定这是否是对你的问题的答案,但希望它能解释一下Python 2和3在这方面的区别。
在Python 2中,iter(d.keys())
和d.iterkeys()
并不完全相同,尽管它们的行为相同。在第一个中,keys()
将返回字典的键列表的副本,iter
将返回此列表上的迭代器对象,第二个键的完整列表的副本永远不会构建。
Python 3中d.keys()
返回的视图对象是 iterable (即可以从它们中创建迭代器)所以当你说for k in d.keys()
Python将创建迭代器时您。因此,您的两个示例将表现相同。
keys()
的返回类型更改的重要性在于Python 3视图对象是动态的。即如果我们说ks = d.keys()
并稍后添加到d
,那么ks
将反映这一点。在Python 2中,keys()
返回当前dict中所有键的列表。比较:
Python 3
>>> d = { "first" : 1, "second" : 2 }
>>> ks = d.keys()
>>> ks
dict_keys(['second', 'first'])
>>> d["third"] = 3
>>> ks
dict_keys(['second', 'third', 'first'])
Python 2.x
>>> d = { "first" : 1, "second" : 2 }
>>> ks = d.keys()
>>> ks
['second', 'first']
>>> d["third"] = 3
>>> ks
['second', 'first']
当Python 3的keys()
返回动态对象时,Python 3没有(并且不需要)单独的iterkeys
方法。
进一步澄清
在Python 3中,keys()
返回一个dict_keys
对象,但如果我们在for
循环上下文for k in d.keys()
中使用它,则会隐式创建迭代器。因此for k in d.keys()
和for k in iter(d.keys())
之间的差异是迭代器的隐式与显式创建之一。
就另一个区别而言,虽然它们都是动态的,但请记住,如果我们创建一个显式迭代器,那么它只能使用一次,而视图可以根据需要重用。 e.g。
>>> ks = d.keys()
>>> 'first' in ks
True
>>> 'second' in ks
True
>>> i = iter(d.keys())
>>> 'first' in i
True
>>> 'second' in i
False # because we've already reached the end of the iterator
另外,请注意,如果我们创建一个显式迭代器然后修改dict,那么迭代器就会失效:
>>> i2 = iter(d.keys())
>>> d['fourth'] = 4
>>> for k in i2: print(k)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
在Python 2中,考虑到keys
的现有行为,需要一个单独的方法来提供一种迭代方法,而不必复制密钥列表,同时仍然保持向后兼容性。因此iterkeys()