讀古今文學網 > 父與子的編程之旅:與小卡特一起學Python > 12.16 字典 >

12.16 字典

從上文可以看出,Python 列表是一種將元素組織在一起的方式。在編程中,你會經常想以另一種方式組織元素,即將某個值和另一個值關聯起來。這種組織方式就像電話通訊錄將姓名和電話號碼關聯起來,也像字典將單詞和它們的含義關聯起來。

Python 字典(dictionary)是一種將兩個東西關聯在一起的方式。被關聯在一起的兩個東西分別稱為鍵(key)和值(value)。字典中的每個項(item)或條目(entry)都有一個鍵和一個值,它們合起來被稱為鍵值對(key-value pair)。一個字典就是一些鍵值對的集合。

一個簡單的例子就是電話通訊錄。假設你想保存朋友們的電話號碼。你會使用他們的姓名去查找他們的號碼(希望你的朋友們沒有重名的)。這個姓名就是「鍵」,即你會用它來查找信息,而電話號碼就是「值」,即你要查找的信息。

下面是創建一個 Python 字典的方法,我們用它來存儲姓名和電話號碼。首先,創建一個空的字典:

>>> phoneNumbers = {}  

這個代碼看起來和創建列表的方式非常像,只不過它使用的是花括號而不是方括號。

然後,我們來添加一個條目:

>>> phoneNumbers[\"John\"] = \"555-1234\"  

如果我們打印一下字典,它看起來是這樣的:

>>> print phoneNumbers{\'John\': \'555-1234\'}  

首先顯示鍵,然後是一個冒號,再接著顯示值。之所以用引號,是因為在這個例子中鍵和值剛好都是字符串(不是必需的)。

也可以用另一種方式來完成:

>>> phoneNumbers = {\"John\": \"555-1234\"}  

我們來添加更多的條目。不像在列表中可以使用 append,在字典中則沒有用於添加新條目的方法。只需要指定新的鍵和值就行了:

>>> phoneNumbers[\"Mary\"] = \"555-6789\">>> phoneNumbers[\"Bob\"] = \"444-4321\">>> phoneNumbers[\"Jenny\"] = \"867-5309\"  

我們來看一下整個字典:

>>> print phoneNumbers{\'Bob\': \'444-4321\', \'John\': \'555-1234\', \'Mary\': \'555-6789\', \'Jenny\': \'867-5309\'}  

我們之所以創建字典,是因為我們可以在字典中查找東西。在這個例子中,我 們希望按姓名來查找電話號碼。你可以這樣做:

>>> print phoneNumbers[\"Mary\"]\'555-6789\'  

注意,這裡使用方括號來指定你想要找的條目的鍵。整個字典本身還是被包裹在花括號中。

字典和列表有點類似,但也有一些主要區別。這兩種類型都稱為「集合」(collection),也就是說,它們都是將其他類型條目集中在一起的組織方式。

它們的一些相似點:

  • 列表和字典都可以包含任意類型(甚至包括列表和字典)的條目,所以你可以有一個包含數字、字符串、對像甚至其他集合的集合。

  • 列表和字典都提供了在集合中查找條目的方法。

它們的一些不同點:

  • 列表是有順序的(ordered)。如果你按照某種順序向列表中添加元素,這些元素就會保持這種順序。你還可以對列表進行排序。字典是無序的(unordered)。如果你向字典中添加內容,然後打印出來,顯示的順序可能會跟添加的順序不同。

  • 列表中的元素是使用索引訪問的,而字典中的條目是使用鍵來訪問的:

    >>> print myList[3]\'eggs\'>>> print myDictionary[\"John\"]\'555-1234\'  

前面提到過,在 Python 中很多東西都是對象,列表和字典也是。所以列表和字典都有一些使用點號表示法來使用的方法。

keys 方法會列出字典中所有的鍵:

>>> phoneNumbers.keys[\'Bob\', \'John\', \'Mary\', \'Jenny\']  

values 方法會列出字典中所有的值:

>>> phoneNumbers.values[\'444-4321\', \'555-1234\', \'555-6789\', \'867-5309\']  

其他的語言也有與 Python 字典類似的東西。它們通常被稱為關聯數組(associative array),因為它們將鍵和值關聯在一起。你可能也會聽說它們的另外一個名字——哈希表(hash table)。

和列表一樣,字典中的條目也可以是任意類型,包括簡單類型(整數、浮點數、字符串)和集合(列表、字典)以及復合類型(對像)。

沒錯,你可以在字典中包含其他的字典,正如列表中可以包含其他的列表一樣。但事實上,這句話並不完全對。只有字典中的值是可以使用字典的,而鍵的要求更為嚴格一些。早先我們談論過可變類型(mutable)與不可變類型(immutable)。字典的鍵只可以使用不可變類型(布爾、整數、浮點數、字符串和元組)。你不能使用一個列表或者字典來當作鍵,因為它們是可變類型。

我在上面提到過,字典和列表有一個不同之處,就是字典是無序的。注意,儘管 Bob 的電話是第三個被添加到字典中的,但在打印字典內容時卻是第一個顯示的。字典沒有順序這個概念,所以對字典進行排序是沒有意義的。但有時你希望將字典中的內容按照某種順序顯示出來。雖然字典沒有順序,但可以對列表排序,所以當你拿到鍵的列表後,就可以對鍵進行排序,然後按照鍵的順序顯示字典內容。你可以使用 sorted 函數來對字典的鍵排序,像下面這樣:

>>> for key in sorted(phoneNumbers.keys):print key, phoneNumbers[key]Bob 444-4321Jenny 867-5309John 555-1234Mary 555-6789  

這和你在列表中看到的 sorted 函數是一樣的。如果你細想一下,會發現它是有效的,因為字典的鍵的集合是一個列表。

那麼,如果你想將字典的值(而不是鍵)按某種順序輸出該怎麼辦呢?在電話通訊錄的例子中,就是按照電話號碼從小到大輸出。字典的查找過程是單向的,這意味著只能用鍵去查找值,而不能反過來。所以對值排序會有些困難。但這仍然是可以做到的,只是需要做更多的工作:

>>> for value in sorted(phoneNumbers.values):for key in phoneNumbers.keys:    if phoneNumbers[key] == value:print key, phoneNumbers[key]Bob 444-4321John 555-1234Mary 555-6789Jenny 867-5309  

我們首先取得排序之後的值的列表,然後針對列表中的每個值,循環遍歷字典中的所有鍵,直到找到與該值關聯的鍵。

下面是字典可以做的其他一些事情。

  • 使用 del 刪除一個條目:

    >>> del phoneNumbers[\"John\"]>>> print phoneNumbers{\'Bob\': \'444-4321\', \'Mary\': \'555-6789\', \'Jenny\': \'867-5309\'  
  • 使用 clear 刪除所有條目(清空字典):

    >>> phoneNumbers.clear>>> print phoneNumbers{}  
  • 使用 in 確定某個鍵在字典中是否存在:

    >>> phoneNumbers = {\'Bob\':\'444-4321\', \'Mary\':\'555-6789\',\'Jenny\':\'867-5309\'}>>> \"Bob\" in phoneNumbersTrue>>> \"Barb\" in phoneNumbersFalse  

字典在 Python 代碼中使用得很廣泛。

這些當然不是有關 Python 字典的全部內容,但你應該對其有了大致的瞭解,這樣你就可以在代碼中使用字典,也可以認出在其他代碼中出現的字典。

你學到了什麼

在這一章,你學到了以下內容。

  • 列表是什麼。

  • 如何向列表中增加元素。

  • 如何從列表刪除元素。

  • 如何確定列表是否包含某個值。

  • 如何對列表排序。

  • 如何建立列表的副本。

  • 元組。

  • 雙重列表。

  • Python 字典。

測試題

1. 向列表增加元素有哪些方法?

2. 從列表刪除元素有哪些方法?

3. 要得到一個列表的有序副本,但又不能改變原來的列表,有哪兩種方法?

4. 怎樣得出某個值是否在列表中?

5. 如何確定某個值在列表中的位置?

6. 什麼是元組?

7. 如何建立雙重列表?

8. 如何從一個雙重列表中得到一個值?

9. 什麼是字典?

10. 如何向字典中增加項?

11. 怎樣使用鍵去查找一個條目?

動手試一試

1. 寫一個程序,讓用戶提供 5 個名字。程序要把這 5 個名字保存在一個列表中,最後打印出來。就像這樣:

Enter 5 names:TonyPaulNickMichelKevinThe names are Tony Paul Nick Michel Kevin  

2. 修改第 1 題的程序,要求不僅顯示原來的名字列表,還要顯示出排序後的列表。

3. 修改第 1 題的程序,要求只顯示用戶鍵入的第 3 個名字,就像這樣:

The third name you entered is: Nick  

4. 修改第 1 題的程序,讓用戶替換其中一個名字。用戶應該能選擇要替換哪個名字,然後鍵入新名字。最後顯示這個新的列表:

Enter 5 names:TonyPaulNickMichelKevinThe names are Tony Paul Nick Michel KevinReplace one name. Which one? (1-5): 4New name: PeterThe names are Tony Paul Nick Peter Kevin  

5. 編寫一個字典程序,讓用戶可以添加單詞和定義,然後可以查找這些單詞。確保當要查找的單詞不存在時,用戶能夠知曉。運行的時候,它應該是像這樣的:

Add or look up a word (a/l)? aType the word: computerType the definition: A machine that does very fast mathWord added!Add or look up a word (a/l)? lType the word: computerA machine that does very fast mathAdd or look up a word (a/l)? lType the word: qwertyThat word isn\'t in the dictionary yet.