python入門基礎(chǔ)字典 如何理解Python中的集合和字典?
如何理解Python中的集合和字典?字典和集合是并且過性能水平距離優(yōu)化的數(shù)據(jù)結(jié)構(gòu),特別是對(duì)于查找、先添加和刪出能操作。本節(jié)將加強(qiáng)實(shí)例介紹它們在具體場景下的性能表現(xiàn),以及與列表等其他數(shù)據(jù)結(jié)構(gòu)的對(duì)比。.例
如何理解Python中的集合和字典?
字典和集合是并且過性能水平距離優(yōu)化的數(shù)據(jù)結(jié)構(gòu),特別是對(duì)于查找、先添加和刪出能操作。本節(jié)將加強(qiáng)實(shí)例介紹它們在具體場景下的性能表現(xiàn),以及與列表等其他數(shù)據(jù)結(jié)構(gòu)的對(duì)比。
.例如,有一個(gè)存儲(chǔ)產(chǎn)品信息(產(chǎn)品ID、名稱和價(jià)格)的列表,現(xiàn)在的需求是,借助某件產(chǎn)品的ID找到什么其價(jià)格。則基于代碼如下:
defvivo_product_price(products,product注冊id):
ofid,priceoutsideproducts:
ifidproduct帳號(hào):
returnprice
returnNone
products[
(111,100),
(222,30),
(333,150)
]
print(Thepriceofproduct222it's{}.format(oppofind_product_price(products,222)))
運(yùn)行結(jié)果為:
Thepriceforproduct222it's30
在上面程序的基礎(chǔ)上,如果沒有列表有n個(gè)元素,只不過里查的過程必須遍歷列表,那么最消極情況下的時(shí)間復(fù)雜度就為O(n)。就算先對(duì)列表接受排序,再建議使用二分查找算法,也是需要O(logn)的時(shí)間復(fù)雜度,況且列表的排序還要O(nlogn)的時(shí)間。
但假如用字典來讀取這些數(shù)據(jù),這樣的話查找變會(huì)更加快捷高效,要O(1)的時(shí)間復(fù)雜度就也可以成功,是因?yàn)槭强梢灾苯油ㄟ^鍵的哈希值,找不到其填寫的值,而不是需要對(duì)字典做遍歷過程不能操作,實(shí)現(xiàn)代碼萬分感謝:
products{
111:100,
222:30,
333:150
}
print(Thepricetheproduct222are{}.format(products[222]))
運(yùn)行結(jié)果為:
Thepriceforproduct222it's30
有些讀者可能對(duì)時(shí)間復(fù)雜度卻沒非常直觀的認(rèn)識(shí),沒什么關(guān)系,再給大家簡要概括一個(gè)實(shí)例。下面的代碼中,初始化操作了含有100,000個(gè)元素的產(chǎn)品,并共有換算出了在用列表和集合來統(tǒng)計(jì)數(shù)據(jù)產(chǎn)品價(jià)格數(shù)量的運(yùn)行時(shí)間:
#統(tǒng)計(jì)時(shí)間是需要會(huì)用到time模塊中的函數(shù),了解即可
importtime
defx2系列_unique_price_using_list(products):
unique_price_list[]
for_,priceintoproducts:#A
ifpricenotunique_price_list:#B
unique_price_(price)
returnlen(unique_price_list)
id[xafterxofrange(0,100000)]
price[xwhilexinrange(200000,300000)]
productslist(zip(id,price))
#換算列表版本的時(shí)間
start_using_list_counter()
x2系列_unique_price_using_list(products)
end_using_list_counter()
print(timeelapseusinglist:{}.format(end_using_list-start_using_list))
#不使用集合能夠完成雖然的工作
defoppofind_unique_price_using_set(products):
unique_price_setset()
for_,priceintoproducts:
unique_price_(price)
returnlen(unique_price_set)
#換算數(shù)學(xué)集合版本的時(shí)間
start_using_set_counter()
find_unique_price_using_set(products)
end_using_set_counter()
print(timeelapseusingset:{}.format(end_using_set-start_using_set))
運(yùn)行結(jié)果為:
timeelapseusinglist:68.78650900000001
timeelapseusingset:0.010747099999989018
可以看到,不僅僅十萬的數(shù)據(jù)量,兩者的速度差異就這般之大。而而不企業(yè)的后臺(tái)數(shù)據(jù)應(yīng)該有上億乃至于十億數(shù)量級(jí),所以要是建議使用了不合適的數(shù)據(jù)結(jié)構(gòu),非常容易導(dǎo)致服務(wù)器的崩潰,而且影響不大用戶體驗(yàn),因此會(huì)給公司給了龐大無比的財(cái)產(chǎn)損失。
這樣的話,字典和集合我想知道為什么能如此又高效,特別是中搜索、插入和刪掉你操作呢?
字典和子集的工作原理
字典和真包含于能如此高效率,和它們內(nèi)部的數(shù)據(jù)結(jié)構(gòu)緊密的聯(lián)系。類似于其他數(shù)據(jù)結(jié)構(gòu),字典和數(shù)學(xué)集合的內(nèi)部結(jié)構(gòu)也是張哈希表:
相對(duì)于字典而言,這張表存儲(chǔ)文件了哈希值(hash)、鍵和值這3個(gè)元素。
而對(duì)集合來說,哈希表內(nèi)只存儲(chǔ)文件元素單一的元素。
對(duì)此以前版本的Python來說,它的哈希表結(jié)構(gòu)如下所示:
|哈希值(hash)鍵(key)值(value)
.|...
0|hash0key0value0
.|...
1|hash1key1value1
.|...
2|hash2key2value2
.|...
這種結(jié)構(gòu)的弊端是,不斷哈希表的擴(kuò)張,它會(huì)變的越來越大稀稀疏疏。比如說,有這樣一個(gè)字典:
{name:mike,dob:1999-01-01,gender:male}
那么它會(huì)讀取為相似下面的形式:
entries[
[--,--,--]
[-230273521,dob,1999-01-01],
[--,--,--],
[--,--,--],
[1231236123,name,mike],
[--,--,--],
[9371539127,gender,male]
]
看樣子,那樣的很白白浪費(fèi)存儲(chǔ)空間。為了提高存儲(chǔ)空間的利用率,現(xiàn)在的哈希表之外字典本身的結(jié)構(gòu),會(huì)把索引和哈希值、鍵、值另分開,也就是采用如下這種結(jié)構(gòu):
Indices
---------------------------------------------------- one | index | None | None | index | None | index...
----------------------------------------------------
Entries
--------------------
hash0key0value0
---------------------
hash1key1value1
---------------------
hash2key2value2
---------------------
...
---------------------
在此處,上面的字典在新哈希表結(jié)構(gòu)下的存儲(chǔ)形式為:indices [None,1,None, None,0,None,2]
entries[
[1231236123,name,mike],
[-230273521,dob,1999-01-01],
[9371539127,gender,male]
]
差不多也可以發(fā)現(xiàn),空間利用率能夠得到很小的提高。
明白了具體看的設(shè)計(jì)結(jié)構(gòu),接下來的事情再講一下如何修改哈希表完成對(duì)數(shù)據(jù)的插入、查找和刪掉不能操作。
哈希表直接插入數(shù)據(jù)
當(dāng)向字典中插入到數(shù)據(jù)時(shí),Python會(huì)簡單依據(jù)鍵(key)換算出對(duì)應(yīng)的哈希值(實(shí)際hash(key)函數(shù)),而向集合中直接插入數(shù)據(jù)時(shí),Python會(huì)依據(jù)什么該元素本身換算按的哈希值((valuse)函數(shù))。
的或:
dic{name:1}
print(hash(name))
setDemo{1}
print(hash(1))
運(yùn)行結(jié)果為:
8230115042008314683
1
得到哈希值(的或?yàn)閔ash)之后,再結(jié)合字典或集合要存儲(chǔ)數(shù)據(jù)的個(gè)數(shù)(或者n),就這個(gè)可以能得到該元素應(yīng)該直接插入到哈希表中的位置(諸如,可以不用hash%n的)。
假如哈希表中此位置是空的,這樣的話此元素就這個(gè)可以就插到其中;反之,要是此位置已被其他元素電腦資源,那就Python會(huì)比較好這兩個(gè)元素的哈希值和鍵是否是相等:
如果沒有互相垂直,則因?yàn)樵撛卦缇痛嬖诘兀俦容^比較他們的值,不成比例就通過自動(dòng)更新;
如果不是不成比例,這種稱做哈希(即兩個(gè)元素的鍵有所不同,但求得的哈希值是一樣的)。這種下,Python會(huì)建議使用剛剛開放定址法、再哈希法等再繼續(xù)去尋找哈希表中空余的位置,直到此時(shí)找不到位置。
具體遇見哈希時(shí),各解決方法的具體含義可閱讀《哈希表詳解》一節(jié)做細(xì)致了解。
哈希表查看數(shù)據(jù)
在哈希表中中搜索數(shù)據(jù),和插入操作類似,Python會(huì)參照哈希值,不能找到該元素應(yīng)該存儲(chǔ)文件到哈希表中的位置,然后再和該位置的元素比較好其哈希值和鍵(子集再也很元素值):
假如之和,則相關(guān)證明不能找到;
或且,則相關(guān)證明當(dāng)初讀取該元素時(shí),遇到了哈希,需要再繼續(xù)可以使用當(dāng)初解決哈希的方法進(jìn)行查看,等他找到該元素或者不能找到空位為止。
這里的不能找到空位,意思是哈希表中沒有存儲(chǔ)目標(biāo)元素。
哈希表刪除掉元素
相對(duì)于徹底刪除操作,Python會(huì)還沒有對(duì)這個(gè)位置的元素融注三個(gè)特殊的方法的值,等到恢復(fù)變動(dòng)哈希表的大小時(shí),再將其刪掉。
需要注意的是,哈希的發(fā)生而不會(huì)減少字典和子集操作的速度。并且,目的是可以保證其高效性,字典和集合內(nèi)的哈希表,大多數(shù)會(huì)能保證其至少留有1/3的剩下的空間。緊接著元素的不斷地插到,當(dāng)其余空間小于1/3時(shí),Python會(huì)原先聲望兌換大內(nèi)存空間,擴(kuò)充隊(duì)伍哈希表,與此同時(shí),表內(nèi)所有的元素位置都會(huì)被新的氣體排放。
python字典語法書寫格式?
①大多數(shù)是一行一句
②也這個(gè)可以一行多句,用語句分隔符“”對(duì)兩個(gè)語句進(jìn)行標(biāo)有
③也這個(gè)可以一句多行,有時(shí)語句過長,一行放不下他,用續(xù)行符“”通過標(biāo)示