字典對象的核心是散列表。散列表是一個稀疏數組(總是有空白元素的數組),數組的每個單元叫做bucket。
每個bucket有兩部分:一個是鍵對象的引用,一個是值對象的引用
由於,所有bucket結構和大小一致,我們可以通過偏移量來讀取指定bucket
將一個鍵值對放進字典的底層過程:
假設字典a對象創建後,數組長度為8
我們要把‘name’='cs’這個鍵值對放進字典對象a中,首先第一步需要計算鍵“name”的散列值。Python中可以通過hash()來計算
#打印的結果為:0b10011001000000110000011001111011111011111100101100111111011001
print(bin(hash(“name”)))
由於數組長度為8,我們可以拿計算出的散列值的最右邊3位數字作為偏移量,即“001”,十進制是數字1,我們查看偏移量1,對應的bucket是否為空。
如果為空,則將鍵值對放進去。如果不為空,則依次取右邊3位作為偏移量,即“011”,十進制是數字3,再查看偏移量為3的bucket是否為空。
直到找到為空的bucket放進去,如果都不為空,那數組就進行擴容,然後偏移量就會發生改變,直到將鍵值對放進去
數組擴容:如果數組有2/3已經滿了,那麼數組就會進行擴容,變的更大
根據鍵查找“鍵值對”的底層過程:與鍵值對放進字典的流程類似
注意:因為偏移量最開始是3位3位開始找,我們不確定是不是相同的一個“鍵值對”,所以我們找到了以後會把找到的“鍵”拿出來計算散列值,如果散列值相同,則返回
如果不同,說明不是同一個“鍵值對”,那就繼續找,直到找到相同的
用法總結:
1.鍵必須是可散列的:
(1)數字,字符串,元組都是可散列的
(2)自定義對象需要支持下面三點:①支持hash()函數 ②支持通過_eq_()方法檢測相同性 ③若a == b 為真,則hash(a)== hash(b)也為真
2.字典在內存中開銷巨大,典型的空間換時間
3.鍵查詢速度很快
4.往字典裡面添加新建肯導致擴容,導致散列表中鍵的次序變化。因此,不要在遍歷字典的同時進行字典的修改