- Python程序設計
- 張雪萍主編
- 4137字
- 2019-06-19 15:48:30
2.7 字典
2.7.1 字典概述及聲明
本節我們將介紹一種新的數據結構——字典,屬于核心數據類型——映射。字典可以說是Python中除了列表使用頻率最高的一個數據類型。
那究竟什么是字典呢?對于字典必須先明確兩個概念:鍵(key)和對應值(value)。因為有些時候,有些數據的結構往往是成對出現的,每一個鍵對應一個值,我們要保存它們之間的關系,要把很多這樣的項目(一對,即一個鍵和一個對應值)添加到一個大的數據結構中,在這種情況下就非常適合使用字典。例如,我們想建立一個電話號碼本,人名就可以當作一個鍵(key),每一個電話號碼就可以是這個鍵(人名)的對應值(value)(見表2-12)。
表2-12 鍵與對應值示例

以上這種數據結構就叫作字典(dictionary)。
1.字典的特性
1)通過鍵(key)而非下標索引(位置偏移)訪問數據
相對于列表來講,字典的數據訪問不是通過下標索引,而是通過它的鍵來完成的。這里的鍵叫作“key”,它所存儲的值叫作“value”,所以它的存儲結構基本上就是一個鍵一個值,即平時我們所說的鍵值對。
2)可包含任意對象的無序集合
當在創建列表時,它里邊的元素的順序跟創建時候的順序是保持一致的,并且可以通過特定的方法或全局函數來將列表中的元素進行排序。但在默認的字典中,它的元素是無序的,通過后面的代碼將會看到,創建字典時的順序和呈現時的順序可能會不一樣[4]。

說明:顯示的順序可能和聲明時的順序并不保持一致。
3)可變長度、異質、可以任意嵌套
這一點和列表非常類似,只是它的存儲結構有差異而已。
4)屬于可變映射
序列有可變序列和不可變序列之分。在映射中,字典屬于可變映射。
5)對象引用表(Hash Table)
這個特點與它的存儲本質有關,它是一個對象引用的表,它的存儲機制就是平時所說的哈希表。
2.創建字典的方法
Python 中的字典用大括號表示,每個項目的鍵和對應值之間用冒號分隔,冒號左邊是鍵,右邊是對應值;每個項目之間用“,”分隔。因為 Python 是一門非常靈活的語言,所以,在同一個字典中,可以包含多種不同類型的數據。
1)創建一個空字典{}

2)創建包含若干元素的字典{key:value}
在介紹創建包含多個數據的字典之前,先了解一下字典跟元組和列表之間的區別。
使用列表可以存儲一系列的信息,假定想聲明一個學生信息,當然,這個學生信息可能會包含很多內容,可能要關注他的姓名、學號、年齡及他的籍貫等。這時,可以把這幾個值放在一個列表里,因為列表可以包含任意的對象。

在創建列表的時候,開發人員明確知道它的第一、第二、第三個元素對應的是什么信息,但是計算機并不了解,或者說你的開發伙伴并不明白你的意圖是什么。也就是說,如果想進一步描述"Tom"是指姓名、19 是指年齡,等等,則需要做更多的工作。因此,要存儲這一類有特定標簽的值,列表并不是最好的選擇,此時就可以使用字典來表示。
用花括號來表示字典,將我們所關注的信息的標簽和實際的值用鍵值對的方式來進行存儲。比如關注姓名,那就輸入字符串"name",之后輸入一個冒號,再輸入"Tom",這便是第一個鍵值對,然后逗號分隔,繼續輸入第二個鍵值對等,這樣就聲明了一個字典結構的學生信息。其中"name"是一個鍵,"Tom"是一個值。

可能你會發現這個順序和聲明的時候不一致了,當然也可能是一致的。這對應字典“可包含任意對象的無序集合”的特性,即它的順序是不確定的。事實上,在 Python中,如果確實需要一個能夠保存正確順序的字典也是可以的,但它屬于另外一個數據類型,并且在一個專門的包中,它是擴展的字典,而這里介紹的是標準的字典。
注意:在實際開發過程中,字典中的鍵不一定是字符串,也可以是浮點型數值、元組,但是基本要求是它的鍵只能是不可變的元素,可變的元素如列表是不能作為鍵的,這一點一定要注意。

雖然從語法上來說,整數、小數、元組,只要是不可變的元素都是可以作為鍵,但在實際開發的時候,鍵是有實際意義的,代表具體的要存儲的信息。
3.類型轉換——dict()函數
在介紹整型、浮點型、列表、元祖時,都有一系列的全局函數,如 int()、float()、list()、tuple()等將某一個特定的對象轉換為目標類型。在字典中也有一個 dict()函數,它能夠將參數中指定的信息轉換為字典的數據結構。其語法如下:

注意:括號里參數的形式和一般函數參數傳入的方式不同,是以關鍵字參數形式進行傳參的。鍵值對是以參數的形式傳入的,鍵等于什么值,即將函數參數指定的對象轉化為對應的目標類型。這里要傳入的是鍵值對的信息,鍵 key 和對應值 value 以等號作為分隔符形成一個鍵值對,一個鍵值對作為一個參數,多個參數即多個鍵值對之間仍然用逗號進行分隔。

以上結果表明這種聲明方式與用花括號方式聲明的結果并沒有什么區別。
但請注意:在用 dict()函數聲明字典的方式中,以參數等于值(key=value)的形式呈現,參數在輸入對不要加引號(字符串),不加引號聲明的鍵默認會加上一個引號。即它以字符串的類型來轉換輸入的鍵。但這種聲明方式的鍵不能是整型、浮點數型、元組及列表。
實際上,使用 dict()函數的形式來聲明字典,還有更多更靈活的方式,比如將一個列表轉換為一個字典。注意:列表的每個元素又是一個元組或一個列表。
dict([(key,value),(key,value)]):將由元組構成的列表轉換為字典。

在這種構造字典的方法中,列表的元素也可以是一個列表,甚至一些元素是列表,另一些元素是元組也是可以的,但這沒有太大的實際意義,只是單純地從語法角度來說是可行的。實際使用時我們盡量避免這種情況,因為一個知識點的學習和掌握是用來解決實際問題的,如果實際場景中并沒有這種現象,我們就不要單純地從語法角度去理解。
假設現在有一個列表包含了一些信息,現在希望把列表所存儲的信息作為字典的鍵,如已有列表keys=['name','age','job'],希望把列表keys的信息轉換成字典的3個鍵,能否進行這樣的轉換?我們知道字典總是以鍵值對的形式來存儲的,現在沒有值只有鍵可以嗎?
4.字典的方法fromkeys()
通過字典里的一個方法 fromkeys()來聲明,將列表中的每個元素作為字典里的一個鍵,沒有值的地方設定為“None”,就是空對象。當然它的值是可以修改的,后面會介紹是如何修改的。

利用 dict()函數進行轉換時,有兩種方式,一種是鍵值對以“key=value”的形式傳入,另一種是傳入的參數是一個序列,或者可迭代對象,它們是有規律的鍵值對。另外,使用 dict()自帶的方法 fromkeys()也能進行轉換(注意:不是函數,而是一個方法轉換),此時是將一個序列的值作為字典的鍵來進行轉換的,鍵所對應的值設定為“None”。
在實際開發過程中,聲明字典的兩種常用方法是使用花括號聲明鍵值對、冒號隔開({key:value}),以及使用函數進行轉換,鍵值對中間以等號隔開(dict(key=value))。
5.元素去重
一個字典中不允許同一個鍵出現兩次,即每個鍵都是獨一無二的!因此,將一個列表或元組轉換成字典的過程實際上達到了將相同的多余元素刪除的目的。
2.7.2 字典元素的訪問
字典是一個無序的結構,對字典的訪問操作是通過鍵而不是下標索引來進行的。同樣,對字典元素的修改、增加,或者刪除字典元素也都是通過鍵而非下標索引來進行的。假設定義了字典dt,對字典元素的訪問操作如表2-13所示。
表2-13 字典元素的訪問操作

2.7.3 字典常用方法
字典在Python內部已經采用面向對象方式實現了,靈活使用字典的方法可以提高編寫代碼的效率。字典的常用方法如表2-14所示。
表2-14 字典的常用方法

關于字典常用方法的幾點說明:
1)get()方法的使用

通過 get()方法訪問字典元素的方式與中括號的訪問方式的區別:即使訪問的鍵不存在,它也不會拋出異常,而是返回一個“None”。如果返回“None”不能滿足要求,還可以返回提示信息。如:

這里,后一項“未找到!”為方法 get()未能成功獲取時返回的一個默認值(字符串),這樣可能更能滿足實際開發時的需求。
2)獲取所有鍵:字典名.keys()
當訪問元素的時候,不管是用中括號還是 get()方法,它總是根據給定的一個鍵得到相對應的一個值,而在有些情況下,希望得到字典的所有的鍵,或者是所有的值,又或者是所有的鍵值對,此時可以通過方法 keys()來得到所有的鍵。其返回的類型是一個視圖,跟列表很像,并可以將獲得的視圖轉換成列表。

類型“dict_keys”本質是一個視圖,但是在實際開發的過程中,如果希望像列表一樣對它進行操作,那就把它轉換成列表。如果只是希望循環打印它的結果,則不用轉換列表而直接用fon-in遍歷循環就能達成目標。


3)獲取所有鍵值對:字典名.items()
如果希望一次獲取字典所有的鍵值對信息,利用方法 items()可以實現這個目的。注意,方法items()得到的仍然是一個視圖,但視圖里的鍵值對是用元組呈現的。

方法 items()得到的每一個鍵值對數據放在一個元組里,元組的第一個元素是鍵,第二個元素是值。因此,可以通過 for-in 遍歷循環打印輸出每一個鍵值對信息(“.format()”格式中的花括號是占位符)。

4)復制字典:字典名.copy()
一般不要用賦值的方式來將一個字典賦值給另一個字典,因為這時它們指向的是同一個對象,對一個字典進行操作會影響另一個字典的元素。如果的確新建的字典的信息來自一個已經創建好了的字典,此時可以通過方法copy()來完成。
5)更新字典:字典名1.update(字典名2)
方法 update()是用字典 2 中的元素來更新字典 1 中的相同元素,不同的元素添加到字典 1 里,所以,該方法實際上是合并更新(當兩個字典里沒有相同的元素時就相當于合并)。看下面的例子。

強調:字典中的信息都是按鍵值對的形式存儲的,存儲的值都是普通的字段或一個嵌套的字典。而在實際開發工作中,字典的值不僅僅局限于某一個常規類型的字典值,它也可以是一個行為方法——函數。函數是定義一個行為的,其實可以將一個函數作為值賦給一個字典。
比如有一個自定義函數say_hello()。在聲明一個字典的時候,希望把“say_hello()”這個行為作為字典中一個鍵的值,那么直接在值的地方輸入“say_hello”,但請注意,此時在“say_hello”后千萬不要加小括號,因為加上小括號表示在此處執行函數say_hello(),并且將執行函數返回的值放在這個地方這不是我們希望的。仔細理解下面的代碼:

注意:在訪問字典的元素時,如果想執行“say_hello”這個行為方法,正確的表示方式是person['hello'](),由于person['hello']獲得鍵'hello'的值,而鍵'hello'所對應的值是一個函數的函數名 say_hello,因此,這里的 person['hello']就相當于“say_hello”這個函數的名稱,要想調用該函數,就必須加上括號。
這一點非常靈活,今后在實際項目開發中可用它實現很多有效或有趣的功能。
Python 的數據結構是比較有特色的,活用字典、列表兩種數據結構會有出人意料的效果。
字典可以理解成封裝好的哈希表,可以非常方便地處理樹形結構。
- Extending Jenkins
- C# 7 and .NET Core Cookbook
- 數據庫系統教程(第2版)
- Game Programming Using Qt Beginner's Guide
- 數據庫系統原理及MySQL應用教程
- 數據結構(Python語言描述)(第2版)
- Visual Basic程序設計實驗指導(第4版)
- JavaScript入門經典
- 軟件測試技術指南
- The DevOps 2.5 Toolkit
- Bootstrap 4 Cookbook
- CoffeeScript Application Development Cookbook
- OpenCV with Python By Example
- JSP程序設計實例教程(第2版)
- Natural Language Processing with Python Quick Start Guide