2010-09-01 71 views
38

如果我理解正確,在Python 2中,iter(d.keys())d.iterkeys()相同。但是現在,d.keys()是一個視圖,它位於列表和迭代器之間。視圖和迭代器之間有什麼區別?在Python 3中迭代字典項(),值(),keys()

換句話說,在Python 3,什麼是

for k in d.keys() 
    f(k) 

for k in iter(d.keys()) 
    f(k) 

而且之間的差異,如何做這些差異的簡單for循環顯示(如果有的話)?

回答

53

我不確定這是不是你的問題的答案,但希望它能解釋一下Python 2和3在這方面的區別。

在Python 2中,iter(d.keys())d.iterkeys()並不完全等價,儘管它們的行爲相同。首先,keys()將返回字典的密鑰列表的副本,然後iter將在此列表上返回一個迭代器對象,第二個密鑰的完整列表副本將永遠不會構建。

通過d.keys()在Python 3返回的視圖對象是迭代(即一個迭代器可以從他們製作),所以當你說for k in d.keys() Python會爲你創建的迭代器。因此你的兩個例子將表現相同。

keys()返回類型變化的意義在於Python 3視圖對象是動態的。即如果我們說ks = d.keys()並且稍後添加到d那麼ks將反映這一點。在Python 2中,keys()返回字典中當前所有鍵的列表。比較:

的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())之間的區別是迭代器的隱式或顯式創建之一。

就另一個區別而言,雖然它們都是動態的,但請記住,如果我們創建顯式迭代器,那麼它只能使用一次,而視圖可以根據需要重用。例如

>>> 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 

另外,還要注意,如果我們建立一個明確的迭代器,然後修改字典那麼迭代器失效:

>>> 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()

+5

2.7中有'.viewkeys()'。它返回視圖。 http://docs.python.org/library/stdtypes.html#dict.viewkeys – phadej 2010-09-01 11:23:10

+0

謝謝。我理解Python 2的'd.keys()'是如何不同的。但是我仍然對Python 2中的'd.iterkeys()',Python 3中的'd.keys()'和Python 3中的'iter(d.keys())'之間的區別感到困惑。據我瞭解,他們都是充滿活力的,他們都沒有提前列出清單? – max 2010-09-01 11:41:13

+0

在'for'循環中,'iter(d.keys())'和'd.keys()'沒有區別,因爲python內部調用iter'本身。 python 2.x'd.iterkeys()'和py3k'iter(d.keys())'之間也沒有區別:都返回dictionary-key-iterator。所以三者幾乎都是一樣的。 – phadej 2010-09-01 12:02:39