使用字典

Python 中的字典是键值对的集合。 每个键都连接到一个值,您可以使用键访问与该键关联的值。 键的值可以是数字、字符串、列表,甚至是另一个字典。 事实上,您可以使用您可以在 Python 中创建的任何对象作为字典中的值。 在 Python 中,字典用大括号 ({}) 包裹,大括号内有一系列键值对,如前面的示例所示:

alien_0 = {'color': 'green', 'points': 5}

键值对是一组相互关联的值。 当您提供一个键时,Python 返回与该键关联的值。 每个键都用冒号连接到它的值,各个键值对用逗号分隔。 您可以在字典中存储任意数量的键值对。

最简单的字典只有一对键值对,如 alien_0 字典的修改版本所示:

alien_0 = {'color': 'green'}

这个字典存储了一条关于 alien_0 的信息:外星人的颜色。 字符串 'color' 是这个字典中的一个键,它的关联值为 'green'。

访问字典中的值

要获取与键关联的值,请给出字典的名称,然后将键放在一组方括号内,如下所示:

alien_0 = {'color': 'green'}
print(alien_0['color'])

这将返回与字典 alien_0 中的键 'color' 关联的值:

green

字典中可以有无限数量的键值对。 例如,这是带有两个键值对的原始 alien_0 字典:

alien_0 = {'color': 'green', 'points': 5}

现在您可以访问 alien_0 的颜色或点值。 如果玩家击落了这个外星人,您可以使用如下代码查看他们应该获得多少分:

alien_0 = {'color': 'green', 'points': 5}

new_points = alien_0['points']
print(f"You just earned {new_points} points!")

定义字典后,我们从字典中提取与键“点”关联的值。 然后将该值分配给变量 new_points。 最后一行打印关于玩家刚刚获得多少分的声明:

You just earned 5 points!

如果您在每次击落外星人时都运行此代码,则会检索外星人的点值。

添加键值对

字典是动态结构,您可以随时向字典添加新的键值对。 要添加新的键值对,您可以在字典名称后跟方括号中的新键以及新值。

让我们向 alien_0 字典添加两条新信息:外星人的 x 和 y 坐标,这将帮助我们在屏幕上的特定位置显示外星人。 让我们把外星人放在屏幕的左边缘,距离顶部向下 25 像素。 因为屏幕坐标通常从屏幕的左上角开始,我们将通过将 x 坐标设置为 0 将外星人放置在屏幕的左边缘,并将其 y 坐标设置为正值,将其放置在距离顶部 25 像素的位置 25,如下所示:

alien_0 = {'color': 'green', 'points': 5}
print(alien_0)

alien_0['x_position'] = 0
alien_0['y_position'] = 25
print(alien_0)

我们首先定义我们一直在使用的同一个字典。 然后我们打印这本字典,显示其信息的快照。 接下来,我们向字典中添加一个新的键值对:键 'x_position' 和值 0。我们对键’y_position' 执行相同的操作。 当我们打印修改后的字典时,我们会看到两个额外的键值对:

{'color': 'green', 'points': 5}
{'color': 'green', 'points': 5, 'x_position': 0, 'y_positio
n': 25}

字典的最终版本包含四个键值对。 最初的两个指定颜色和点值,另外两个指定外星人的位置。

字典保留它们被定义的顺序。 当您打印字典或循环遍历其元素时,您将看到元素的顺序与它们添加到字典中的顺序相同。

从创建一个空字典开始

有时从一个空字典开始,然后向其中添加每个新项目,这很方便,甚至是必要的。 要开始填充一个空字典,请定义一个带有一组空大括号的字典,然后将每个键值对添加到它自己的行中。 例如,以下是使用这种方法构建 alien_0 字典的方法:

alien_0 = {}

alien_0['color'] = 'green'
alien_0['points'] = 5

print(alien_0)

我们首先定义一个空的 alien_0 字典,然后向其中添加颜色和点值。 结果是我们在前面的例子中使用的字典:

{'color': 'green', 'points': 5}

通常,在将用户提供的数据存储在字典中或编写自动生成大量键值对的代码时,您会使用空字典。

修改字典中的值

要修改字典中的值,请在方括号中给出字典名称和键,然后是您希望与该键相关联的新值。 例如,考虑一个随着游戏的进行从绿色变为黄色的外星人:

alien_0 = {'color': 'green'}
print(f"The alien is {alien_0['color']}.")

alien_0['color'] = 'yellow'
print(f"The alien is now {alien_0['color']}.")

我们首先为 alien_0 定义一个字典,它只包含外星人的颜色; 然后我们将与键 'color' 关联的值更改为 'yellow'。 输出显示外星人确实从绿色变成了黄色:

The alien is green.
The alien is now yellow.

举一个更有趣的例子,让我们跟踪一个可以以不同速度移动的外星人的位置。 我们将存储一个表示外星人当前速度的值,然后用它来确定外星人应该向右移动多远:

alien_0 = {'x_position': 0, 'y_position': 25, 'speed': 'medium'}
print(f"Original position: {alien_0['x_position']}")

# Move the alien to the right.
# Determine how far to move the alien based on its current speed.
if alien_0['speed'] == 'slow': (1)
    x_increment = 1
elif alien_0['speed'] == 'medium':
    x_increment = 2
else:
    # This must be a fast alien.
    x_increment = 3

# The new position is the old position plus the increment.
alien_0['x_position'] = alien_0['x_position'] + x_increment (2)

print(f"New position: {alien_0['x_position']}")
1 我们首先定义一个具有初始 x 位置和 y 位置以及“中等”速度的外星人。 为了简单起见,我们省略了颜色和点值,但如果您也包含这些键值对,则此示例将以相同的方式工作。 我们还打印 x_position 的原始值,以查看外星人向右移动了多远。 一个 if-elif-else 链确定外星人应该向右移动多远,并将这个值赋给变量 x_increment 。

如果外星人的速度“慢”,它向右移动一个单位; 如果速度为“中等”,则向右移动两个单位; 如果它是“快”,它向右移动三个单位。 计算出增量后,将其添加到 x_position 的值,并将结果存储在字典的 x_position 中。

因为这是一个中速外星人,所以它的位置向右移动了两个单位:

Original x-position: 0
New x-position: 2

这项技术非常酷:通过更改外星人字典中的一个值,您可以改变外星人的整体行为。 例如,要将这个中速外星人变成快速外星人,您可以添加以下行:

alien_0['speed'] = 'fast'

if-elif-else 块会在代码下次运行时为 x_increment 分配一个更大的值。

删除键值对

当您不再需要存储在字典中的一条信息时,您可以使用 del 语句完全删除键值对。 del 只需要字典的名称和要删除的键。

例如,让我们从 alien_0 字典中删除键 'points' 及其值:

alien_0 = {'color': 'green', 'points': 5}
print(alien_0)

del alien_0['points'] (1)
print(alien_0)
1 del 语句告诉 Python 从字典 alien_0 中删除键 'points' 并删除与该键关联的值。

输出显示键“points”及其值 5 已从字典中删除,但字典的其余部分不受影响:

{'color': 'green', 'points': 5}
{'color': 'green'}

注意删除的键值对是永久移除的。

由类似的对象组成的字典

前面的示例涉及存储关于一个对象(游戏中的外星人)的不同类型的信息。 您还可以使用字典来存储关于许多对象的一种信息。 例如,假设您想对一些人进行民意调查并询问他们最喜欢的编程语言是什么。 字典对于存储简单轮询的结果很有用,如下所示:

favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'rust',
    'phil': 'python',
    }

如您所见,我们将一个更大的字典分成了几行。 每个键是响应民意调查的人的名字,每个值是他们的语言选择。 当您知道需要不止一行来定义字典时,请在左大括号后按 ENTER。 然后将下一行缩进一级(四个空格)并写入第一个键值对,后跟一个逗号。 从此时开始,当您按 ENTER 键时,您的文本编辑器应自动缩进所有后续键值对以匹配第一个键值对。

完成定义字典后,在最后一个键值对之后的新行上添加一个右大括号,并将其缩进一层,使其与字典中的键对齐。 在最后一个键值对之后也包含一个逗号是一种很好的做法,这样您就可以在下一行添加一个新的键值对了。

大多数编辑器都具有一些功能,可帮助您以与此示例类似的方式格式化扩展列表和词典。 其他可接受的格式化长词典的方法也可用,因此您可能会在编辑器或其他来源中看到略有不同的格式。

要使用这个字典,给定参加投票的人的姓名,您可以轻松查找他们最喜欢的语言:

favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'rust',
    'phil': 'python',
    }

language = favorite_languages['sarah'].title()
print(f"Sarah's favorite language is {language}.")

要查看 Sarah 选择了哪种语言,我们需要以下值:

favorite_languages['sarah']

我们使用此语法从字典中提取 Sarah 最喜欢的语言,并将其分配给变量语言。 在这里创建一个新变量可以使 print() 调用更加清晰。 输出显示了 Sarah 最喜欢的语言:

Sarah's favorite language is C.

您可以对字典中表示的任何个人使用相同的语法。

使用get()来访问值

使用方括号中的键从字典中检索您感兴趣的值可能会导致一个潜在的问题:如果您要求的键不存在,您将得到一个错误。

让我们看看当您询问没有设置点值的外星人的点值时会发生什么:

alien_0 = {'color': 'green', 'speed': 'slow'}
print(alien_0['points'])

这导致回溯,显示 KeyError:

Traceback (most recent call last):
  File "alien_no_points.py", line 2, in <module>
    print(alien_0['points'])
         ~~~~~~~^^^^^^^^^^
KeyError: 'points'

您将在第 10 章中了解更多关于如何处理此类错误的信息。特别是对于字典,您可以使用 get() 方法设置一个默认值,如果请求的键不存在,该值将被返回。

get() 方法需要一个键作为第一个参数。 作为第二个可选参数,如果键不存在,您可以传递要返回的值:

alien_0 = {'color': 'green', 'speed': 'slow'}

point_value = alien_0.get('points', 'No point value assigned.')
print(point_value)

如果字典中存在关键字 'points' ,您将获得相应的值。 如果没有,您将获得默认值。 在这种情况下,点不存在,我们得到一条干净的消息而不是错误:

No point value assigned.

如果您要求的键可能不存在,请考虑使用 get() 方法而不是方括号表示法。

如果在调用 get() 时省略了第二个参数并且键不存在,Python 将返回值 None。 特殊值 None 表示“不存在任何值”。 这不是错误:它是一个特殊值,表示缺少值。 您将在第 8 章中看到 None 的更多用途。

自己试试
6-1.Person

使用字典来存储您认识的人的信息。 存储他们的名字、姓氏、年龄和他们居住的城市。 您应该有名字、姓氏、年龄和城市等键。 打印存储在字典中的每条信息。

6-2.Favorite Numbers

使用字典来存储人们最喜欢的号码。 想出五个名字,并将它们用作字典中的关键字。 为每个人想出一个最喜欢的数字,并将每个数字作为一个值存储在您的字典中。 打印每个人的名字和他们最喜欢的号码。 为了获得更多乐趣,请投票给几个朋友并为您的程序获取一些实际数据。

6-3.Glossary

Python 字典可用于为实际字典建模。 但是,为避免混淆,我们称其为词汇表。 想一想你在前几章中学到的五个编程词汇。 使用这些词作为词汇表中的键,并将它们的含义存储为值。 将每个单词及其含义打印为格式整齐的输出。 您可以打印单词后跟一个冒号,然后打印它的含义,或者在一行上打印单词,然后在第二行打印其含义缩进。 使用换行符 (\n) 在输出中的每个词义对之间插入一个空行。