字典(Dictionary)
成都創(chuàng)新互聯(lián)公司是一家專業(yè)提供城西企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、HTML5、小程序制作等業(yè)務(wù)。10年已為城西眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。
字典也是Python語言中經(jīng)常使用的一種數(shù)據(jù)類型。跟列表類似,字典是另外一種可存儲(chǔ)任意類型的數(shù)據(jù),并且字典儲(chǔ)存的數(shù)據(jù)也是可以修改的。
不同于列表的是,字典每個(gè)基本元素都包括兩個(gè)部分:鍵(key) 和 鍵對(duì)應(yīng)的值(value)。
鍵和值之間用冒號(hào)(:)分割,每對(duì)元素之間用逗號(hào)(,)分割,整個(gè)字典的數(shù)據(jù)在大括號(hào){}中,格式如下所示:
請(qǐng)點(diǎn)擊輸入圖片描述
d = {"key1" : 1, "key2" : "hi", "key3":[]}
在字典中,鍵的內(nèi)容是不可重復(fù)的。?鍵為不可變數(shù)據(jù)類型,值可以是任何數(shù)據(jù)類型。在這里,鍵只支持?字符串類型。
請(qǐng)點(diǎn)擊輸入圖片描述
請(qǐng)點(diǎn)擊輸入圖片描述
字典最大的優(yōu)勢就是能在海量數(shù)據(jù)下利用“鍵”快速查找出想要的值,?當(dāng)有很多數(shù)據(jù)需要存儲(chǔ)的時(shí)候,我們給每個(gè)值都打個(gè)標(biāo)簽,也就是“鍵”;想要調(diào)用這個(gè)值時(shí),字典能夠利用這個(gè)標(biāo)簽快速幫我們找到它。但是如果標(biāo)簽重復(fù)了,字典不知道哪個(gè)值才是對(duì)的,就會(huì)報(bào)錯(cuò)哦~
列表是根據(jù)排序來記錄每項(xiàng)的值,但是字典是沒有順序的,所以同一字典,每次打印出的排序可能是不同的?!版I”才是調(diào)用字典的關(guān)鍵元素。
字典是基礎(chǔ)的數(shù)據(jù)類型,所以變量也可以被賦值為字典。
請(qǐng)點(diǎn)擊輸入圖片描述
請(qǐng)點(diǎn)擊輸入圖片描述
可以直接用大括號(hào){},或者內(nèi)置函數(shù)dict()?創(chuàng)建空字典:
Dict={}Dict=dict() #dict()是一個(gè)內(nèi)置函數(shù),可以用來快速創(chuàng)建空字典。#注意是小寫開頭的dict,創(chuàng)建變量名或者函數(shù)名要避免和內(nèi)置函數(shù)dict重名哦~
控制中的遍歷積木,不僅可以遍歷序列、列表,還可以遍歷字典
請(qǐng)點(diǎn)擊輸入圖片描述
x = input("請(qǐng)輸入X的值:")
dict1 = {"1":"001","2":"010","3":"011","4":"100"}
x_print= ""
for i in x:
x_print = x_print + dict1[i]
print(x_print)
我的python是3.6的語法可能不太一樣
dir(dict)?#這會(huì)列出dict的所有成員函數(shù)
help(dict.xxx)?#這會(huì)給出dict的成員函數(shù)xxx的幫助文檔
dict對(duì)象是Python中一個(gè)原始的數(shù)據(jù)類型,按照鍵值對(duì)的方式存儲(chǔ),中文名為字典,其通過鍵名查找對(duì)應(yīng)的值有很高的效率,時(shí)間復(fù)雜度在常數(shù)級(jí)別O(1)。Python dict的底層是依靠哈希表(Hash Table)進(jìn)行實(shí)現(xiàn)的,使用開放地址法解決沖突。所以其查找的時(shí)間復(fù)雜度會(huì)是O(1),why?
哈希表是key-value類型的數(shù)據(jù)結(jié)構(gòu),通過關(guān)鍵碼值直接進(jìn)行訪問。通過散列函數(shù)進(jìn)行鍵和數(shù)組的下標(biāo)映射從而決定該鍵值應(yīng)該放在哪個(gè)位置,哈希表可以理解為一個(gè)鍵值需要按一定規(guī)則存放的數(shù)組,而哈希函數(shù)就是這個(gè)規(guī)則。
算法中時(shí)間和空間是不能兼得的,哈希表就是一種用合理的時(shí)間消耗去減少大量空間消耗的操作,這取決于具體的功能要求。
創(chuàng)建一個(gè)數(shù)組,數(shù)組下標(biāo)是索引號(hào),數(shù)組中的值是要獲得的數(shù)據(jù),這樣只需要O(1)的時(shí)間復(fù)雜度就可以完成操作,但是擴(kuò)展性不強(qiáng),有以下兩個(gè)方面的考慮:
-1- 新添加的元素超出數(shù)組索引范圍,這就需要重新申請(qǐng)數(shù)組進(jìn)行遷移操作。
-2- 假設(shè)一種極端的情況:只存在兩個(gè)元素,索引號(hào)分別是1和100000000001,按照先前的設(shè)計(jì)思路,會(huì)浪費(fèi)很大的存儲(chǔ)空間。
會(huì)不會(huì)存在一個(gè)方法,為已有的索引創(chuàng)建新的索引,通過壓縮位數(shù),讓新索引可以和原有的大范圍的稀疏索引進(jìn)行一一對(duì)應(yīng),新索引所需要的存儲(chǔ)空間要大大減小,這就是哈希思想。
上面的例子中哈希函數(shù)的設(shè)計(jì)很隨意,但是從這個(gè)例子中我們也可以得到信息:
哈希函數(shù)就是一個(gè)映射,因此哈希函數(shù)的設(shè)定很靈活,只要使得任何關(guān)鍵字由此所得的哈希函數(shù)值都落在表長允許的范圍之內(nèi)即可;
因?yàn)樾碌乃饕龑?duì)舊的索引進(jìn)行了空間上的壓縮,所以不可能所有的輸入都只對(duì)應(yīng)唯一一個(gè)輸出,也就是哈希函數(shù)式有可能發(fā)生沖突的,哈希函數(shù)不可能做成一對(duì)一的映射關(guān)系,其本質(zhì)是一個(gè)多對(duì)一的映射。
直接定址法:很容易理解,key=Value+C; 這個(gè)“C”是常量。Value+C其實(shí)就是一個(gè)簡單的哈希函數(shù)。
除法取余法: 很容易理解, key=value%C;解釋同上。
數(shù)字分析法:這種蠻有意思,比如有一組value1=112233,value2=112633,value3=119033,針對(duì)這樣的數(shù)我們分析數(shù)中間兩個(gè)數(shù)比較波動(dòng),其他數(shù)不變。那么我們?nèi)ey的值就可以是key1=22,key2=26,key3=90。
平方取中法。此處忽略,見名識(shí)意。
折疊法:這種蠻有意思,比如value=135790,要求key是2位數(shù)的散列值。那么我們將value變?yōu)?3+57+90=160,然后去掉高位“1”,此時(shí)key=60,哈哈,這就是他們的哈希關(guān)系,這樣做的目的就是key與每一位value都相關(guān),來做到“散列地址”盡可能分散的目地。
當(dāng)兩個(gè)不同的數(shù)據(jù)元素的哈希值相同時(shí),就會(huì)發(fā)生沖突。解決沖突常用的手法有2種:
開放地址法:
如果兩個(gè)數(shù)據(jù)元素的哈希值相同,則在哈希表中為后插入的數(shù)據(jù)元素另外選擇一個(gè)表項(xiàng)。當(dāng)程序查找哈希表時(shí),如果沒有在第一個(gè)對(duì)應(yīng)的哈希表項(xiàng)中找到符合查找要求的數(shù)據(jù)元素,程序就會(huì)繼續(xù)往后查找,直到找到一個(gè)符合查找要求的數(shù)據(jù)元素,或者遇到一個(gè)空的表項(xiàng)。
鏈接法:
將哈希值相同的數(shù)據(jù)元素存放在一個(gè)鏈表中,在查找哈希表的過程中,當(dāng)查找到這個(gè)鏈表時(shí),必須采用線性查找方法。
python的dict采用了哈希表,最低能在 O(1)時(shí)間內(nèi)完成搜索,在發(fā)生哈希沖突的時(shí)候采用的是開放尋址法。java的HashMap也是采用了哈希表實(shí)現(xiàn),但是在發(fā)生哈希沖突的時(shí)候采用的是鏈接法。
Python中dict對(duì)象是表明了其是一個(gè)原始的Python數(shù)據(jù)類型,按照鍵值對(duì)的方式存儲(chǔ),其中文名字翻譯為字典,顧名思義其通過鍵名查找對(duì)應(yīng)的值會(huì)有很高的效率,時(shí)間復(fù)雜度在常數(shù)級(jí)別O(1).dict底層實(shí)現(xiàn)(推薦學(xué)習(xí):Python視頻教程)
在Python2中,dict的底層是依靠哈希表(Hash Table)進(jìn)行實(shí)現(xiàn)的,使用開放地址法解決沖突.
所以其查找的時(shí)間復(fù)雜度會(huì)是O(1).
Dict的操作實(shí)現(xiàn)原理(包括插入、刪除、以及緩沖池等)
首先介紹:PyDictObject對(duì)象的元素搜索策略:
有兩種搜索策略,分別是lookdict和lookdict_string,lookdict_string就是lookdict在對(duì)于PyStringObject進(jìn)行搜索時(shí)的特殊形式,那么通用的搜索策略lookdict的主要邏輯是:
(1)對(duì)第一個(gè)entry的查找:
a)根據(jù)hash值獲得entry的索引
b)若entry處于unused態(tài),則搜索結(jié)束;若entry所指向的key與搜索的key相同,則搜索成功
c)若當(dāng)前entry處于dummy態(tài),則設(shè)置freeslot(這里的freeslot是可以返回作為下一個(gè)立即可用的地址來存儲(chǔ)entry)
d)檢查Active態(tài)的entry,若其key所指向的值與搜索的值相同,則搜索成功
(2)對(duì)剩余的探測鏈中的元素的遍歷查找:
a)根據(jù)所采用的探測函數(shù),獲得探測鏈上的下一個(gè)待檢查的entry
b)檢查到一個(gè)unused態(tài)的entry,表明搜索失敗:
如果freeslot不為空,則返回freeslot;否則返回unused態(tài)的entry
c)檢查entry的key與所搜索的key的引用是否相同,相同則搜索成功,返回entry
d)檢查entry的key與所搜索的key的值是否相同,相同則搜索成功,返回entry
e)遍歷過程中,發(fā)現(xiàn)dummy態(tài)的entry,且freeslot未設(shè)置,則設(shè)置freeslot
接下來是:PyDictObject對(duì)象的元素插入與刪除的策略:
需要首先用到搜索策略,搜索成功,則直接將值進(jìn)行替換,搜索失敗,返回unused態(tài)或dummy態(tài)的entry,設(shè)置key、value和hash值,并且根據(jù)目前插入的元素情況進(jìn)行ma_table的大小的調(diào)整(調(diào)整的依據(jù)就是裝載率,根據(jù)是否大于2/3來進(jìn)行調(diào)整);刪除也是類似,先計(jì)算hash值,然后搜索相應(yīng)的entry,搜索成功,刪除entry中維護(hù)的元素,將entry從Active態(tài)修改為dummy態(tài)
在PyDictObject的實(shí)現(xiàn)過程中,會(huì)用到緩沖池,在PyDictObject對(duì)象被銷毀的時(shí)候,才開始接納被緩沖的PyDictObject對(duì)象,定義的緩沖池可接納的對(duì)象數(shù)量是80個(gè),創(chuàng)建新PyDictObject對(duì)象的時(shí)候,如果緩沖池中有,則可以直接從緩沖池中取出使用
更多Python相關(guān)技術(shù)文章,請(qǐng)?jiān)L問Python教程欄目進(jìn)行學(xué)習(xí)!以上就是小編分享的關(guān)于python dict怎么實(shí)現(xiàn)的的詳細(xì)內(nèi)容希望對(duì)大家有所幫助,更多有關(guān)python教程請(qǐng)關(guān)注環(huán)球青藤其它相關(guān)文章!
記住一點(diǎn)python字典是無序的 不要被假象迷惑 至于key為數(shù)字時(shí)能自動(dòng)排序是為什么 我也不清楚 但是你可以利用這一特性 在之后需要對(duì)dic中的value進(jìn)行排序時(shí) 就可以用數(shù)字當(dāng)key