首页 » 父与子的编程之旅:与小卡特一起学Python » 父与子的编程之旅:与小卡特一起学Python全文在线阅读

《父与子的编程之旅:与小卡特一起学Python》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.