在刷題的時候看到很多時候題目要用到ordereddict,不是很理解這樣做的目的,看到解析說是要按照插入的順序儲存和取出。當時就很疑惑,親自試驗了預設的dict也能夠實現順序儲存和取出。
在3.6版本之前,python dict底層在初始建立的時候採用的是indice和儲存合併在乙個二維陣列當中。dictionary採用雜湊表原理,key作為取值物件,進行hash(key)操作,得到雜湊值,然後用值進行 % 字典容量得到要插入的位置。
my_dict[
'age']=
26my_dict[
'salary']=
999999
## dictionary結構[[
-4234469173262486640
, 指向salary的指標, 指向999999的指標],[
1545085610920597121
, 執行age的指標, 指向26的指標],[
---,
---,
---]
,[--
-,--
-,--
-],[
---,
---,
---]
,[1278649844881305901
, 指向name的指標, 指向kingname的指標],[
---,
---,
---]
,[--
-,--
-,--
-]]
取值 和存放都是進行hash然後取模,直接訪問這個二位陣列。當你要迴圈遍歷字典的key的時候,python底層會遍歷這個二維陣列,如果當前行有資料,那麼就返回key指標對應的記憶體裡面的值。如果當前行沒有資料,那麼就跳過。所以總是會遍歷整個二位陣列的每一行。
每一行有三列,每一列占用8byte的記憶體空間,所以每一行會占用24byte的記憶體空間。
由於hash值取餘數以後,餘數可大可小,所以字典的key並不是按照插入的順序存放的
開放定址,當兩個不同的key,經過hash以後,再對8取餘數,可能餘數會相同。此時python為了不覆蓋之前已有的值,就會使用開放定址技術重新尋找乙個新的位置存放這個新的鍵值對。
當字典的鍵值對數量超過當前陣列長度的2/3時,陣列會進行擴容,8行變成16行,16行變成32行。長度變了以後,原來的餘數字置也會發生變化,此時就需要移動原來位置的資料,導致插入效率變低。
在版本3.6之後,字典的底層資料結構發生了變化,現在當你初始化乙個空的字典以後,它在底層是這樣的:
my_dict[
'address']=
'***'
my_dict[
'salary']=
999999
## 此時的記憶體示意圖
indices =[1
,0,none
,none
,none
,none,2
,none
]entries =[[
-5954193068542476671
, 指向name的指標, 執行kingname的指標],[
9043074951938101872
, 指向address的指標,指向***的指標],[
7324055671294268046
, 指向salary的指標, 指向999999的指標]
]
實際資料儲存和索引進行分開存放,indices是資料存放在二維陣列的位置,其他內容保持不變。這樣就保證了dictionary在新增新的鍵值對的時候是按照順序進行依次存放的。當去讀取dict內容的時候
>>
>
hash
('salary'
)7324055671294268046
>>
>
hash
('salary')%
86
那麼我就去讀indices下標為6的這個值。這個值為2.
然後再去讀entries裡面,下標為2的這一行的資料,也就是salary對應的資料了。
新的這種方式,當我要插入新的資料的時候,始終只是往entries的後面新增資料,這樣就能保證插入的順序。當我們要遍歷字典的keys和values的時候,直接遍歷entries即可,裡面每一行都是有用的資料,不存在跳過的情況,減少了遍歷的個數。
老的方式,當二維陣列有8行的時候,即使有效資料只有3行,但它占用的記憶體空間還是 8 * 24 = 192 byte。但使用新的方式,如果只有三行有效資料,那麼entries也就只有3行,占用的空間為3 * 24 =72 byte,而indices由於只是乙個一維的陣列,只占用8 byte,所以一共占用 80 byte。記憶體占用只有原來的41%。
Python 字典理解
目錄 初始化乙個空字典 給字典增加一對 鍵 值 key value 使用鍵來呼叫值 改變字典裡的值 字典是物件引用 字典對鍵和值的迭代 參考 obj print obj output 字典的鍵和值之間存在一一對映關係,且 鍵 值對 在字典中的放置是毫無順序的 obj obj one 1 obj tw...
Python字典的原理
python中dict物件是表明了其是乙個原始的python資料型別,按照鍵值對的方式儲存,其中文名字翻譯為字典,顧名思義其通過鍵名查詢對應的值會有很高的效率,時間複雜度在常數級別o 1 本文針對其實現的資料結構進行原理性說明和拓展,不涉及python的原始碼剖析。dict底層實現 在python2...
Python 字典實現原理
a a key1 1 a key2 6 del a key1 python直譯器 執行 a python直譯器讀到這裡,比如會給5個連續的記憶體空間,有5個連續的記憶體位址,可以放資料 python直譯器 執行 a key1 1 這裡,python直譯器會對key1進行雜湊運算,得到乙個十位進製的雜...