標籤:

第三章 字典和集合

dict類型不但在各種程序里被廣泛的使用,這也是Python語言的基石。

正是因為dict類型的重要,Python對其的實現做了高度的優化,

其中最重要的原因就是背後的「散列表」nset(集合)和dict一樣,其實現基礎也是依賴於散列表。

什麼是可散列的數據類型?

如果一個對象是可散列的,那麼在這個對象的生命周期中,他的散列值是不變的。並且,這個對象需要實現__hash__()方法。另外該對象還需要實現__qe__()方法,這樣才能和其他的鍵做比較,如果兩個可散列的對象是相等的,那麼他們的hash值一定是一樣的。

字典的推導:

n字典推導的應用nnnDIAL_CODE = [n (86, China),n (91, India),n (7, Russia),n (81, Japan),n]nn# 利用字典推導快速生成字典ncountry_code = {country: code for code, country in DIAL_CODE}nprint(country_code)nn# 將區域碼最為鍵,國家名作為值,並過濾掉區域碼大於等於86的國家:ncountry_code_1 = {code: country for code, country in DIAL_CODE if code < 86}nprint(country_code_1)nnnOUT:n{China: 86, India: 91, Russia: 7, Japan: 81}nn{7: Russia, 81: Japan}nn

字典的推導,可以從任何以鍵值對為元素的可迭代的對象中快速構建出字典。

如果列表的推導的概念你已經十分的清楚,那麼接受字典的推導應該不是很難。n如果你覺得還有所障礙,那麼是時候話費功夫來掌握他了!

字典的變種

標準庫里collections模塊中提供了很多與字典類型相似的變種。

OrderDict:n這個類型在添加鍵的時候,會保存順序,因此鍵的迭代順序總是一致的

ChainMap:n該類型可以容納數個不同的映射對像,在進行鍵的查找時,這些對象會被當做一個整體逐個查找,直到鍵被找到為止

Counter:n這個映射類型會給鍵準備一個整數技術器,每次更行一個鍵的時候都會增加這個計數器,所以這個類型可以用來給散列表對象計數,或者當成多重集來用。

import collectionsnnct = collections.Counter(asdfghjk)nprint(ct)nct.update(qweqweqweqwe)nprint(ct)nprint(ct.most_common(2))nnnCounter({a: 1, s: 1, d: 1, f: 1, g: 1, h: 1, j: 1, k: 1})nCounter({q: 4, w: 4, e: 4, a: 1, s: 1, d: 1, f: 1, g: 1, h: 1, j: 1, k: 1})n[(q, 4), (w, 4)]nn

UserDict:n這個類其實就是把標準的dict,用Python又寫了一遍。

不可變映射類型

說到不可變,一定很多人想到了 元組,n但是實際上元組裡的元素在某些時候,還是可以變的,n當你需要一個不可變的映射類型的時候,types模塊里的MappingProxyType可以幫到你。

from types import MappingProxyTypenn# 元組裡的第二個元素其實是一個列表的引用。ntest1 = (a,[1,2,3])ntest1[1].append(2)nprint(test1)nn# 不可變映射類型:nd = {1:A}nd_proxy = MappingProxyType(d)nprint(d_proxy)nd_proxy[1]=Bnprint(d_proxy)nnn(a, [1, 2, 3, 2])n{1: A}nTraceback (most recent call last):n File "/Users/ehco/Documents/codestuff/Fluent-Python/第三章字典和集合/3-7.py", line 13, in <module>n d_proxy[1]=BnTypeError: mappingproxy object does not support item assignmentnn

集合論

集合的本質是需對唯一對象的聚集,因此集合可以用於去重

集合具有唯一性,與此同時,集合還實現了很多基礎的中綴運算符:n給定兩個集合A、B:nA | B 得到他們的合集(全集)nA & B 得到他們的交集。。。

合理的利用這些特性,不僅能減少代碼的書寫數量,更能增加運行的效率

# 利用集合去重:nl = [1,1,2,3,1,1,1,2,3]nprint(set(l))nnA = [1,2,3,4,5]nB = [2,3,4,5,6]nn# 找到AB交集的個數nprint(len(set(A)&set(B)))nnnOUT:nn{1, 2, 3}n4nn

dict的實現以及導致的結果

  • 鍵必須是可散列的
  • 字典在內存上開銷很大(用內存換效率)
  • 鍵的查詢很快
  • 鍵的次序取決於添加順序
  • 往字典里添加新鍵可能會改變已有鍵的順序

set的實現以及導致的結果

  • 結合的元素必須是可散列的
  • 集合和消耗內存
  • 可以很高效的判斷元素是否存在於某個集合
  • 元素的次序取決於被添加到集合里的順序
  • 往集合里添加元素,可能會改變集合里已有的元素次序

本章小結

這一章主要介紹了dict、set等映射序列的知識,n尤其著重介紹了「散列」的基本概念。

大多數的映射類型都提供了兩個很強大的方法:setdefault,updatensetdefault方法可以用來更新字典里存放的可變值,從而避免了重複搜索nupdate方法讓批量更新成為可能

dict和set背後的散列效率很高,對散列的概念了解的越深刻,就越能理解到n「速度是以犧牲空間為代價而換來的」

推薦閱讀:

如何爬取全網1200本Python書|爬蟲實戰篇
Python實現3D建模工具
聊聊Python,談談未來
OpenCV:圖片操作基本知識
如何去尋找網路爬蟲的需求?

TAG:Python |