145 Python字典(dict)底層實現原理

2021-09-25 18:07:40 字數 2294 閱讀 5226

字典也被稱為關聯陣列,還稱為雜湊陣列等。也就是說,字典也是乙個陣列,但陣列的索引是鍵經過雜湊函式處理後得到的雜湊值。雜湊函式的目的是使鍵均勻地分布在陣列中,並且可以在記憶體中以o(1)的時間複雜度進行定址,從而實現快速查詢和修改。雜湊表中雜湊函式的設計困難在於將資料均勻分布在雜湊表中,從而儘量減少雜湊碰撞和衝突。由於不同的鍵可能具有相同的雜湊值,即可能出現衝突,高階的雜湊函式能夠使衝突數目最小化。python中並不包含這樣高階的雜湊函式,幾個重要(用於處理字串和整數)的雜湊函式是常見的幾個型別。通常情況下建立雜湊表的具體過程如下:

把key通過雜湊函式轉換成乙個整型數字,然後就將該數字對陣列長度進行取餘,取餘結果就當作陣列的下標,將value儲存在以該數字為下標的陣列空間裡。

再次使用雜湊函式將key轉換為對應的陣列下標,並定位到陣列的位置獲取value。

雜湊函式就是乙個對映,因此雜湊函式的設定很靈活,只要使得任何關鍵字由此所得的雜湊函式值都落在表長允許的範圍之內即可。本質上看雜湊函式不可能做成乙個一對一的對映關係,其本質是乙個多對一的對映,這也就引出了下面乙個概念–雜湊衝突或者說雜湊碰撞。雜湊碰撞是不可避免的,但是乙個好的雜湊函式的設計需要盡量避免雜湊碰撞。

cpython使用偽隨機探測(pseudo-random probing)的雜湊表(hash table)作為字典的底層資料結構。由於這個實現細節,只有可雜湊的物件才能作為字典的鍵。字典的三個基本操作(新增元素,獲取元素和刪除元素)的平均事件複雜度為o(1)。

python中所有不可變的內建型別都是可雜湊的。

可變型別(如列表,字典和集合)就是不可雜湊的,因此不能作為字典的鍵。

開放定址法中,所有的元素都存放在雜湊表裡,當產生雜湊衝突時,通過乙個探測函式計算出下乙個候選位置,如果下乙個獲選位置還是有衝突,那麼不斷通過探測函式往下找,直到找個乙個空槽來存放待插入元素。

開放位址的意思是除了雜湊函式得出的位址可用,當出現衝突的時候其他的位址也一樣可用,常見的開放位址思想的方法有線性探測再雜湊,二次探測再雜湊等,這些方法都是在第一選擇被占用的情況下的解決方法。

這個方法是按順序規定多個雜湊函式,每次查詢的時候按順序呼叫雜湊函式,呼叫到第乙個為空的時候返回不存在,呼叫到此鍵的時候返回其值。

將所有關鍵字雜湊值相同的記錄都存在同一線性鍊錶中,這樣不需要占用其他的雜湊位址,相同的雜湊值在一條鍊錶上,按順序遍歷就可以找到。

一般情況下,處理衝突方法相同的雜湊表,其平均查詢長度依賴於雜湊表的裝填因子。雜湊表的裝填因子定義為表中填入的記錄數和雜湊表長度的比值,也就是標誌著雜湊表的裝滿程度。直**來,α越小,發生衝突的可能性就越小,反之越大。一般0.75比較合適,涉及數學推導。

在python中乙個key-value是乙個entry,

entry有三種狀態。

unused: me_key == me_value == null

unused是entry的初始狀態,key和value都為null。插入元素時,unused狀態轉換成active狀態。這是me_key為null的唯一情況。

active: me_key != null and me_key != dummy 且 me_value != null

插入元素後,entry就成了active狀態,這是me_value唯一不為null的情況,刪除元素時active狀態刻轉換成dummy狀態。

dummy: me_key == dummy 且 me_value == null

此處的dummy物件實際上乙個pystringobject物件,僅作為指示標誌。dummy狀態的元素可以在插入元素的時候將它變成active狀態,但它不可能再變成unused狀態。

為什麼entry有dummy狀態呢?這是因為採用開放定址法中,遇到雜湊衝突時會找到下乙個合適的位置,例如某元素經過雜湊計算應該插入到a處,但是此時a處有元素的,通過探測函式計算得到下乙個位置b,仍然有元素,直到找到位置c為止,此時abc構成了探測鏈,查詢元素時如果hash值相同,那麼也是順著這條探測鏈不斷往後找,當刪除探測鏈中的某個元素時,比如b,如果直接把b從雜湊表中移除,即變成unused狀態,那麼c就不可能再找到了,因為ac之間出現了斷裂的現象,正是如此才出現了第三種狀態---dummy,dummy是一種類似的偽刪除方式,保證探測鏈的連續性。

提示一般情況下普通的順序表陣列儲存結構也可以認為是簡單的雜湊表,雖然沒有採用雜湊函式(取餘),但同樣可以在o(1)時間內進行查詢和修改。但是這種方法存在兩個問題:擴充套件性不強;浪費空間。

set集合和dict一樣也是基於雜湊表的,只是他的表元只包含值的引用而沒有對鍵的引用,其他的和dict基本上是一致的,所以在此就不再多說了。並且dict要求鍵必須是能被雜湊的不可變物件,因此普通的set無法作為dict的鍵,必須選擇被「凍結」的不可變集合類:frozenset。顧名思義,一旦初始化,集合內資料不可修改。

145 python網路程式設計 UDP繫結資訊

還記得在上一節課中,如果乙個網路程式在每次執行的時候埠是隨機變化的麼?一般情況下,在一天電腦上執行的網路程式有很多,而各自用的埠號很多情況下不知道,為了不與其他的網路程式占用同乙個埠號,往往在程式設計中,udp的埠號一般不繫結 但是如果需要做成乙個伺服器端的程式的話,是需要繫結的,想想看這又是為什麼...

Python 字典 dict 函式

python 字典 dict 函式用於建立乙個新的字典,用法與 pyhon 字典 update 方法相似。dict 函式函式語法 dict key value 引數說明 返回乙個新的字典。以下例項展示了 dict 函式的使用方法 usr bin python3 dict0 dict 傳乙個空字典 p...

python基礎 dict字典

字典概述 1.概述 字典本質上也是乙個集合,是乙個無序的集合,儲存的時候以鍵值對 key value 的方式來進行儲存。它具有極快的查詢速度 2.key的特性 字典中的key必須是唯一的 key必須是不可變物件 不可變物件 str,number,bool,none,tuple 可變物件 list,d...