2008-12-04 36 views
12

字典方法dict.keys(),dict.items() 和dict.values()返回「views」 而不是列表。 http://docs.python.org/dev/3.0/whatsnew//3.0.htmlPython 3.0 - dict方法返回視圖 - 爲什麼?

首先,視圖與迭代器有什麼不同?其次,這種改變的好處是什麼?這是出於性能原因嗎?

它對我來說並不直觀,即我要求一個事物列表(給我所有的鑰匙),並且我還得到其他的東西。這會讓人迷惑嗎?

+0

這是計算器上一個偉大的回答: http://stackoverflow.com/questions/8957750/what-are-python-dictionary-view-objects – Exthen 2013-11-21 01:26:01

+0

貌似網址是死的。 – Borealis 2016-05-02 01:01:55

回答

13

您正在有效地獲取一個列表。它只是不是內部列表的副本,而是表現得好像列表只是表示內部狀態一樣。

這與在Java中實現的方式相同(也可能是其他許多語言/環境)。

主要原因是,對於許多用例來說,返回完全分離的列表是不必要和浪費的。這將需要複製整個內容(可能或很多不是很多)。

如果您只是想遍歷鍵,則不需要創建新列表。如果你真的需要它作爲一個單獨的列表(作爲副本),那麼你可以很容易地從視圖中創建該列表。

6

約阿希姆紹爾的答案很好地解釋了爲什麼list沒有返回。但是這留下了爲什麼這些函數不會返回迭代器的問題,就像iteritems等在Python 2中做的那樣。

迭代器比容器更具限制性。例如,迭代器不允許超過一次傳遞;如果你嘗試第二遍,你會發現它是空的。因此,容器支持諸如elem in cont之類的操作,但迭代器不支持這種操作:一旦檢查了迭代器中的元素是否在「in」中,迭代器就會被破壞!

另一方面,獲取容器通常要求需要複製,如從字典的鍵中創建列表。

view對象具有兩全其美:它表現爲一個容器,但不會製作字典的副本!實際上,它是一種虛擬只讀容器,通過鏈接到底層字典來工作。我不知道它是否在標準Python的其他地方出現過。

編輯:

@AntonyHatchkins:它不返回發電機功能的原因是,它不會允許快速in操作。是的,in適用於發電機功能(當你打電話給他們時)。也就是說,你可以這樣做:

def f(): 
    for i in range(10): 
    yield i 

5 in f() # True 

但根據in的定義,如果右側是一臺發電機,蟒蛇將通過所有的n項目發電機 - 導致O(n)時間複雜度。你無能爲力,因爲這是唯一有意義的行爲,是一個任意的發生器。

在另一方面,在字典視圖的情況下,可以實現in你喜歡的任何方式,因爲你知道更多關於你的管理數據。而事實上in與使用哈希表的O(1)複雜性來實現。您可以通過運行

>>> d = dict(zip(range(50000000), range(50000000))) 
>>> 49999999 in d 
True 
>>> 49999999 in iter(d) # kinda how generator function would work 
True 
>>> 

,並注意到第一in的速度有多快相比,第二in檢查。

0

正如相關的問題已經提到,鑑於有len()方法,它的迭代器缺乏(尚未清單有它)。

返回一個視圖而不是列表的另一個好處是,至少在鍵它在O(1)操作,而不是O(N)的列表(或迭代)優化的會員資格測試。