標籤:

關於 Python 字典的 values() 方法返回值的順序?

dict_mark = {"Wang": "C", "Li": "B", "Ma": "A"}
s = ""
for c in dict_mark.values():
s += c
print(s)

關於這個字典列印出來一直是 CBA 的順序,可是字典不是應該無序嗎?stackoverflow的前輩們的答案我看的一知半解,能否請教知友們呢?

問題地址

另一答案地址

還有一個關於 dictionary 的(字典變有序了?)


無序的不代表隨機的,也不代表每次都是隨機的,這些詞有細微的差異。無序的只是說,你不該對順序有任何假定,既不能假定有確定順序,也不能假定沒有確定順序。


規範是指dict遍歷是不保證順序的,但一定保證每個元素都被遍歷一次

實現可以是無序,也可以是有序,都符合規範

Py3.5是無序的,3.6是有序的,但不能說dict就是有序的,因為如果3.7改成無序的也是正確的實現。

如果要使用有序dict,必須用OrderedDict


如果按照語言規範來看,Python的規範里沒有說明Dict是一個有序的類型。換句話說,dict就是無序的,因為語言規範不保證它按照什麼順序出來。要有序,請使用OrderedDict。

但是無序不是說每次輸出結果都不同,無序只是指結果不保證一定與插入順序一致而已。

CPython 3.6里對dict有個新的實現,使得字典內部存儲的順序不僅僅與key有關,還與插入順序有關。但是有關並不代表它就一定按照插入順序依次出現(似乎當字典實現在內存中進行擴展的時候就可能造成結果不一致),只不過表示如果key相同,插入順序相同,那麼結果也是相同的。

在此之前,用values和keys方法取到的list僅與key(準確的說是key的__hash__)有關而與插入順序無關。


Python dictionary implementation

你看下 dict 的 CPython hash 實現就了解了


一般語言里的dict結構只是表面上說自己是無序的,實際上根據內部實現會有自己的一套順序,只是這個順序可能比較古怪,比較混沌,比較沒有統一標準,甚至可能以後實現變了順序也會變,所以設計者也不想告訴你究竟是個什麼順序,但是每次讀出來都會根據這個順序出。

不過也有比較奇葩的語言每次讀出來的順序都不一樣,比如說golang。


沒有順序,包括.keys取鍵,.values取值,字典無序存儲不是逗你玩的,不管你在命令行里輸出多少次一樣的順序都不要上當!!!

如果要取字典順序,請你老老實實用ordereddict!!

這是我有一次在spark做需求的血淚教訓


Python內部對key的索引是有序的,具體我舉個例子.

In [6]: hash("acc")7

Out[6]: 2

In [7]: hash("abc")7

Out[7]: 4

In [8]: {"acc":"acc","abc":"abc"}

Out[8]: {"abc": "abc", "acc": "acc"}

輸入字典順序是先key"acc"後key"abc",輸出位置就倒了.

當然除了整數hash("key")7的值好像每次重新開一個Python解釋器都會變.所以說可能你的hash("abc")7這個值也會和我的不一樣.

回到你的問題.

In [9]: hash("Wang")7

Out[9]: 1

In [10]: hash("Li")7

Out[10]: 1

In [11]: hash("Ma")7

Out[11]: 5

In [12]: {"Wang": "C", "Li": "B", "Ma": "A"}

Out[12]: {"Li": "B", "Ma": "A", "Wang": "C"}

我現在的字典順序就變了呢.

但是實際上這個返回順序並不重要.


字典是有順序的 但是順序是不定的 不信你可以迭代試試


補充 @靈劍 的回答。

cpython3.6的dict實現搬了pypy的實現,是保持順序的。

** 但你依然不能把dict當作有序的來使用 **

因為dict的標準規定*不保證*有順序,要保證有順序的請用OrderedDict


理論上肯定有序的 你既然有放入的順序 查看肯定就有順序 只是不可以順序的方式看待


字典是無序的,這句話是對的。但是字典的存儲過程卻是按順序的。

字典的存儲背後的邏輯是散列表,也就是稀疏數組。dict初始化之後,Python解釋器會給dict分配一定的空間,往字典里添加是按順序添加的。

但是,如果如果繼續往字典里添加新鍵,有可能會引起Python解釋器對存儲空間的擴容,擴容的過程會新建散列表,然後複製已有的元素到新散列表,這個過程可能會引起散列衝突,導致dict的鍵值對的次序發生變化。

《流暢的Python》一書有關於字典的存儲更為詳細的介紹。

如果不了解散列表,可以查資料。


values 和 keys 保持遍歷時鍵對對應順序一致。


推薦閱讀:

Mixin是什麼概念?
如何學習 Python,面對那麼多的標準庫,應該如何?
Python 在改代碼時怎麼處理縮進問題?
簡歷中如何證明自己的編程能力?
怎樣才能寫出 Pythonic 的代碼?

TAG:Python |