0基礎學Python之十五:字典(上)

https://www.zhihu.com/video/972507283209502720

Hi 大家好,我是王可樂。上節課里,我們介紹了一個獨特的數據類型元組,和列表類似,他們都是保存有序元素集合的數據類型。今天這節課里,可樂會為大家介紹另一個更有趣的數據類型——字典。首先,讓我們再來看看我們前面課程里舉過的一個例子:中學老師王可樂的成績單。

細心的朋友們可能早就發現了一個問題:如果只把成績放到列表裡,我該怎麼知道哪個分數是哪個同學的呢?

一個簡單的方案是:我們再來創建一個列表,用來保存同學的名字。這個列表和保存成績的列表對應,這樣我們用一個下標數字就可以找到一個同學的成績和名字了。可是,這樣的保存方法用起來很麻煩。例如,我們如何實現對成績進行排序的這個需求呢?排序之後,成績的順序亂了,所以名字和成績對應關係就不存在了,還真是傷腦筋啊!

不過你也別著急。可樂今天要給大家介紹這個數據類型——「字典」,就可以用來解決這個問題了。字典,和我們的紙質字典類似,它也是一個集合性質的數據類型。在這個數據類型里,儲存的每一個元素都有兩部分組成,一個叫 key(也叫做關鍵字,或者鍵),另一個叫 value(也稱作值)。字典中的一個關鍵字對應一個值。

說了這麼多抽象的概念,我們還是來看一下實例。首先,我們來看看字典的初始化。

>>> x = {} # 初始化一個字典>>> type(x) # 我們用 type 函數來查看一下,x 的類型是字典,dict<class dict>

這裡,一對空的大括弧,代表了一個空的字典。此外,我們可以在字典初始化的時候直接對字典進行賦值。初始化的時候,關鍵字和值之間要用冒號分隔開。例如:

>>> x = {a:1, 1:2, xyz:[1,2,3]}>>> x # 我們來看一下,x 就是一個字典,以逗號分隔,x 中有三個元素,每個元素冒號前面的是關鍵字 key,冒號後面的則是值 value{a: 1, 1: 2, xyz: [1, 2, 3]}

需要注意的是,字典中的關鍵字是唯一不重複的,而不同關鍵字對應的值則可以重複。我們可以用賦值語句來修改字典,例如:

>>> x[b] = 3.14 # 由於字典中原來沒有 b 這個關鍵字,所以這個操作為字典 x 新增了一個元素>>> x # 我們來看一下,字典變成了這個樣子{a: 1, 1: 2, xyz: [1, 2, 3], b: 3.14}>>> x[b] = 6.28 # 然後,我們再次對 b 賦值,這次換了一個不同的值,由於 b在字典中已經存在了,所以這個語句的作用就是修改了字典中 b 這個關鍵字對應的值>>> x # 我們來查看一下,此時 b 的值已經變成了 6.28{a: 1, 1: 2, xyz: [1, 2, 3], b: 6.28}

和列表或元組類似,可以用方括弧來訪問字典中的一個元素。不同的是,訪問字典中的元素時,方括弧里是該元素的關鍵字。例如:

>>> x[b] # 輸入 x[b],訪問 x 字典中關鍵字為字元串 b 的元素6.28 # 這個元素的值為 6.28>>> x[xyz] # 類似的,訪問關鍵字為字元串 xyz 的元素[1, 2, 3] # Shell 為我們列印出來了對應的值,是一個列表

訪問字典中的元素是,如果方括弧里的關鍵字在字典中不存在,那麼字典會報錯。例如:

>>> x[not_exist]Traceback (most recent call last): File "<stdin>", line 1, in <module>KeyError: not_exist

可以看到,Python 彙報了一個 KeyError,表示關鍵字 not_exist 不存在。

由於字典中的關鍵字是唯一的,字典不像列表一樣存在 + 和 * 操作。對字典使用這兩個操作符的時候,都會得到系統的報錯。但是我們仍然可以用in來檢測某個關鍵字是否在字典里,我們來試一下:

>>> x # 先看一下字典 x 現在的樣子{a: 1, 1: 2, xyz: [1, 2, 3], b: 6.28}>>> a in xTrue # 返回 True>>> c in xFalse # 返回 False

注意,我們只能用in來檢查關鍵字是否存在,並不能用來檢測值是否存在。

和列表、元組類似,字典中包含多個元素,也支持對元素的遍歷。有兩種方式來做這個事情。一種方式是遍歷字典中的關鍵詞,然後用關鍵字去訪問對應的值。例如下面代碼:

>>> for key in x: ... print(key, x[key]) # 然後我們列印出來關鍵詞 key 和對應的值... # 再回車,執行循環語句a 11 2xyz [1, 2, 3]b 6.28

另一種方式是同時取出字典中的關鍵字和值,例如下面代碼:

>>> for key,value in x.items(): # 這裡,我們用 x.items() 得到關鍵字以及值... print(key, value) # 然後,還是列印它們...a 11 2xyz [1, 2, 3]b 6.28

和上面的代碼效果是一樣的。

這裡,可樂要提一下字典的一個很重要的特性,就是字典沒有索引值的概念。和列表、元組不同,字典中的元素是無序的。所以我們在採用上述方式遍歷字典時,Python只保證不會落下字典中的任何一個元素,但是不保證在不同的平台、不同的環境下,包含相同元素的字典一定會有相同順序的關鍵字輸出。

可以打一個比方,字典就好像一個裝滿了雜物的口袋,你要從裡向外掏物品。可以保證把所有的物品都一一掏出來,沒有任何遺漏;但是如果要每兩次掏的順序都一樣,這就不能保證了。那要怎麼樣才能做到每次遍歷時關鍵字的順序都一樣呢?很簡單,我們對所有的關鍵字做一個排序就可以了。舉個例子:

>>> y = {"a":23, "d":46, "c":79, "xyz":7, "h":198} # 首先,定義字典 y>>> keys = list(y.keys()) # 我們用 keys 函數把 y 的關鍵字全部取出來,然後轉換成一個列表,叫做 keys>>> keys # 可以看到,keys 列表包含了字典 y 的所有關鍵字[a, d, c, xyz, h]>>> keys.sort() # 我們對 keys 進行排序>>> keys # 得到排序後的 keys[a, c, d, h, xyz]

然後,我們可以對排序後的列表進行遍歷,並訪問字典中當前關鍵字對應的值,就能實現對字典元素的有序遍歷了。

另外要注意的是,在這個例子里,字典里的所有關鍵字是同一個數據類型的,所以可以正常進行排序。如果關鍵字不是一種數據類型,Python又不知道應該怎麼進行比較,就會報錯了。

最後,我們回到本節課最初提到的例子。經過了今天的學習,我們知道了如何使用字典這個數據結類型,然後就很容易實現姓名到考試成績的存儲和查詢了。由於字典是無序的,沒法支持我們按照考試成績排序,所以我們需要藉助列表來進行處理。我們來看代碼吧:

首先,我們定義一個字典 y,存儲學生姓名到成績的對應數據。

>>> y = {"貂蟬":65, "曹操":90, "韓信":95, "常遇春":50, "李白":80}

然後,我們把 y 中的值和關鍵字,也就是成績和姓名取出來,做成一個列表。代碼如下:

>>> z = list(zip(y.values(), y.keys()))

這行代碼有點複雜,我們來仔細看一下。首先,y.values() 能夠把字典 y 中的全部值都取出來,組成一個類似列表的數據;類似的,y.keys() 能夠把字典中的關鍵字取出來。雖然說取出關鍵字列表、值列表的順序我們不能確定,但是由於是在同一個運行環境下,我們能保證取出來的關鍵字列表和值列表是一一對應的。

然後,我們使用了一個 Python 的內置函數 zip。zip 的功能是接受多個列表,並且把每個列表裡對應位置上的元素打包到一個元組裡。我們在這裡給 zip 先傳入了值的列表,然後傳入了關鍵字的列表,zip 就一一取出兩個列表中的元素,每取出一對構造一個元組。最後,我們用函數 list 把 zip 生成的這些元組對轉換成列表。我們來查看一下結果:

>>> z[(65, 貂蟬), (90, 曹操), (95, 韓信), (50, 常遇春), (80, 李白)] >>> z.sort() # 我們對列表 z 調用 sort 函數>>> z # 查看一下 z,可以看到,我們已經得到了一個按照成績排序的列表了[(50, 常遇春), (65, 貂蟬), (80, 李白), (90, 曹操), (95, 韓信)]

這裡,列表中的對象是元組,我們在調用 sort 時,sort 會利用元組之間的大小比較來進行排序。這裡,可樂為大家補充一下元組比較的規則。對兩個元組進行大小比較時,Python 會從兩個元組的第一個元素開始比較,如果兩個元組第一個元素相同,Python 會繼續比較第二個元素,直到分出大小為止。例如:

>>> (2, b) > (1, a) True # 由於第一個元素 2 比 1 大,因此結果為 True>>> (1, b) > (1, a) True # 這兩個元組第一個元素相同,因此 Python 進一步比較後一個元素,b 大於 a,所以結果也是 True>>> (1, 2, 3) > (1, 2) # 如果兩個元組長度不相等True # 由於兩個元組前兩個元素都一樣,因此比較第三個元素,有第三個元素的元組勝出>>> (1, a) == (1, a) # 當然,兩個元組可以相等True # 返回 True

在我們的例子里,我們只對分數的排序感興趣,因此最終得到了一個按分數順序遞增的列表就足夠了。此外,如果我們想按分數從高到低排,只需用 reverse 函數就可以了。

通過字典和字典操作,我們既實現了按成績的排序,又能快速地找到成績對應的人名。好了,今天的課程就到這裡。今天,我們講到了字典這個數據類型。它又是一個功能強大,應用廣泛的數據類型。我們生活的方方面面,都有著字典的應用場景。例如:商品和價格的對應,人名和身份證號的對應,電影名和男女主角名的對應,小區名和房價的對應等等。

下節課里,可樂還將繼續為大家講解字典的更多知識點,歡迎收看哦。同時,還沒有關注我們公眾號的同學,別忘了掃描屏幕上的二維碼,或者微信搜索「可樂編程」,關注我們。如果你覺得可樂的課程內容比較有趣,也請轉發給你的朋友們,可樂感謝大家的支持,我們下次課再見!


推薦閱讀:

Python 3.7新特性展望
值得收藏|菜鳥學Python【入門文章大全】
數據分析找工作 答疑
WSGI規範(PEP 3333) 第四部分(常見問題)
python高效編程實踐-如何根據字典中值的大小, 對字典中的項排序(4/50)

TAG:Python | 零基礎 | 編程 |