Python原始碼剖析 Dict

2021-07-12 01:03:31 字數 2665 閱讀 8949

為了刻畫某種關係,現代的程式語言都會提供關聯式的容器。關聯式容器中的元素分別是以(鍵(key)或值(value))這樣的形式存在。例如(3,5)(3,6)就是一對對應的鍵與值。

python中的關聯式容器是pydictobject。python通過pydictobject建立執行python位元組碼的執行環境,其中會存放變數名和變數值的元素對,通過查詢變數名獲得變數值。

pydictobject運用了(hash table)雜湊表,最優情況下能達到o(1)複雜度的搜尋效率。

雜湊表:

基本思想:鍵值對映整數,通過一片連續記憶體的索引對應相對的值

雜湊效率高,但是不同的物件運用雜湊函式有可能會產生相同的雜湊值、即是易衝突

缺點:刪除時不能完成刪除元素,否則會造成斷鏈,解決的辦法是:偽刪除

entry/slot ->關聯容器(鍵)

乙個entry的定義如下:

typedef struct pydictentry;

因為key和value 都是pyobject,故什麼東西都可以放進去dict

entry有三種狀態:

①unused態 →key,value = null

②active 態 → key!= dummy,key!=null,value != null

③dummy 態 → key = dummy, value = null

三態的轉換關係如下:

在pydictobject定義中,

定義是分兩種情況:①元素數目小於8, ma_table 指向 ma_smalltable 

②元素數目大於8, ma_table指向額外記憶體

第一次呼叫pynew的時候會建立dummy物件,dummy則指向乙個pystringobject物件

元素的搜尋:lookdict、lookdict_string-(演算法相同)  後者是為鍵值為string提供便利 因為在python中一pystringobject物件作為pydictobject的鍵是十分常見的,故lookdict_string成為了pydictobject中預設的搜尋演算法

dict的key匹配值有兩層含義:

①引用相同,即兩符號指向同一位址

②值相同,兩個物件指向不同的位址,但是值相同

e.g.:python大整數是不共享記憶體的,如下例子:

d = {}

d[9527] = 'python'

print(d[9527])

//上面兩個9527指向不同的位址,但值相同

接下來看看第一次搜尋:

[1]根據hash獲得entry的索引,這裡是第乙個索引

[2]if entry處於unused態,即字典中無這個key,第乙個索引失敗 if entry->me_key ==  key,表明匹配,搜尋成功

[3]if entry 處於dummy態,設定freeslot(最後如果找不到是會返回freeslot,提示系統這裡有乙個dummy,快來用掉它)

[4]if entry 處於active ,檢查是否值相同,若相同則搜尋成功

所第乙個entry不匹配,則沿著探測鏈,順藤摸瓜,依次比較探測鏈上的entry與帶查詢的key

①若搜尋成功,則ep一定指向乙個有效的entry

②若搜尋不成功,此時ep肯定處於乙個unused態的entry

不能直接返回,因為有可能在搜尋鏈的過程中發現dummy,故須返回給python使用

lookdict_string(有條件限制)(優化)

key是pydictobject

if(!pystring_checkecact(key))
lookdict_string 效率比lookdict高

元素插入:

ep = mp->ma_lookup(mp, key, hash);

成功:

if (ep->me_value != null)
else將key, value覆給ep(ep可以為dummy,unused)

在插入元素的動作結束後,會檢查是否需要改變pydictobject內部ma_table的記憶體大小

條件:當增加元素個數且裝載率大於2/3時

改變記憶體大小由dictresize執行

[1]確定新的table大小,這個大小要大於傳入的數值,從8開始乘以2的指數倍(2的n此方),直到超過傳入的數值

[2]==8,不需要重新分配記憶體,直接指向ma_smalltable

[3]>=8,重新分配記憶體

[5]對非unused做處理,若為active則插入,若為dummy則丟棄,也就是重新做字典,類似乙個新字典裡面是沒有dummy的

[6]如果舊的table指向記憶體(>8)則釋放

刪除:與插入很像,先計算hash值,找到相對應的entry,刪除維護的元素,將active轉為dummy,調整table使用情況(ma_used--1)

字典結束

redis原始碼剖析 dict

typedef struct dictentry v struct dictentry next dictentry typedef struct dicttype dicttype this is our hash table structure.every dictionary has two ...

python原始碼剖析 Python原始碼剖析

第頁共 頁python 原始碼剖析 物件機制 1.物件 在python 的世界中,一切都是物件,乙個整數是乙個物件,乙個字串也是 乙個物件,更為奇妙的是,型別也是乙個物件,整數型別是乙個物件,字串類 型也是乙個物件。從 年guido 在那個聖誕節揭開 python 世界的大幕開始,一直到現在,pyt...

原始碼剖析 Hashtable 原始碼剖析

hashtable同樣是基於雜湊表實現的,同樣每個元素都是key value對,其內部也是通過單鏈表解決衝突問題,容量不足 超過了閾值 時,同樣會自動增長。hashtable也是jdk1.0引入的類,是執行緒安全的,能用於多執行緒環境中。hashtable同樣實現了serializable介面,它支...