6.3 遍历字典
一个Python字典可能只包含几个键值对,也可能包含数百万个键值对。鉴于字典可能包含大量数据,Python支持对字典进行遍历。字典可用于以各种方式存储信息,因此有多种遍历方式:可遍历字典的所有键值对,也可仅遍历键或值。
6.3.1 遍历所有键值对
探索各种遍历方法前,先来看一个新字典,它用于存储有关网站用户的信息。下面的字典存储一名用户的用户名、名和姓:
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}
利用本章前面介绍过的知识,可访问user_0 的任何一项信息,但如果要获悉该用户字典中的所有信息,该如何办呢?可使用for 循环来遍历这个字典:
user.py
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}
❶ for key, value in user_0.items():
❷ print(f"\nKey: {key}")
❸ print(f"Value: {value}")
如❶所示,要编写遍历字典的for 循环,可声明两个变量,用于存储键值对中的键和值。这两个变量可以使用任意名称。下面的代码使用了简单的变量名,这完全可行:
for k, v in user_0.items()
for 语句的第二部分包含字典名和方法items() (见❶),它返回一个键值对列表。接下来,for 循环依次将每个键值对赋给指定的两个变量。在本例中,使用这两个变量来打印每个键(见❷)及其相关联的值(见❸)。第一个函数调用print() 中的"\n" 确保在输出每个键值对前都插入一个空行:
Key: username
Value: efermi
Key: first
Value: enrico
Key: last
Value: fermi
在6.2.6节的示例favorite_languages.py中,字典存储的是不同人的同一种信息。对于类似这样的字典,遍历所有的键值对很合适。如果遍历字典favorite_languages ,将得到其中每个人的姓名和喜欢的编程语言。由于该字典中的键都是人名,值都是语言,因此在循环中使用变量name 和language ,而不是key 和value 。这让人更容易明白循环的作用:
favorite_languages.py
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
❶ for name, language in favorite_languages.items():
❷ print(f"{name.title()}'s favorite language is {language.title()}.")
❶处的代码让Python遍历字典中的每个键值对,并将键赋给变量name ,将值赋给变量language 。这些描述性名称能够让人非常轻松地明白函数调用print() (见❷)是做什么的。
仅使用几行代码,就将全部调查结果显示出来了:
Jen's favorite language is Python.
Sarah's favorite language is C.
Edward's favorite language is Ruby.
Phil's favorite language is Python.
即便字典存储的是上千乃至上百万人的调查结果,这种循环也管用。
6.3.2 遍历字典中的所有键
在不需要使用字典中的值时,方法keys() 很有用。下面来遍历字典favorite_languages ,并将每个被调查者的名字都打印出来:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
❶ for name in favorite_languages.keys():
print(name.title())
❶处的代码行让Python提取字典favorite_languages 中的所有键,并依次将它们赋给变量name 。输出列出了每个被调查者的名字:
Jen
Sarah
Edward
Phil
遍历字典时,会默认遍历所有的键。因此,如果将上述代码中的:
for name in favorite_languages:
替换为:
for name in favorite_languages.keys():
输出将不变。
显式地使用方法keys() 可让代码更容易理解,你可以选择这样做,但是也可以省略它。
在这种循环中,可使用当前键来访问与之相关联的值。下面来打印两条消息,指出两位朋友喜欢的语言。像前面一样遍历字典中的名字,但在名字为指定朋友的名字时,打印一条消息,指出其喜欢的语言:
favorite_languages = {
—snip—
}
❶ friends = ['phil', 'sarah']
for name in favorite_languages.keys():
print(f"Hi {name.title()}.")
❷ if name in friends:
❸ language = favorite_languages[name].title()
print(f"\t{name.title()}, I see you love {language}!")
❶处创建了一个列表,其中包含要收到打印消息的朋友。在循环中,打印每个人的名字,并检查当前的名字是否在列表friends 中(见❷)。如果在,就打印一句特殊的问候语,其中包含这位朋友喜欢的语言。为获悉朋友喜欢的语言,我们使用了字典名,并将变量name 的当前值作为键(见❸)。
每个人的名字都会被打印,但只对朋友打特殊消息:
Hi Jen.
Hi Sarah.
Sarah, I see you love C!
Hi Edward.
Hi Phil.
Phil, I see you love Python!
还可使用方法keys() 确定某个人是否接受了调查。下面的代码确定Erin是否接受了调查:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
❶ if 'erin' not in favorite_languages.keys():
print("Erin, please take our poll!")
方法keys() 并非只能用于遍历:实际上,它返回一个列表,其中包含字典中的所有键。因此❶处的代码行只核实'erin' 是否包含在这个列表中。因为她并不包含在这个列表中,所以打印一条消息,邀请她参加调查:
Erin, please take our poll!
6.3.3 按特定顺序遍历字典中的所有键
从Python 3.7起,遍历字典时将按插入的顺序返回其中的元素。不过在有些情况下,你可能要按与此不同的顺序遍历字典。
要以特定顺序返回元素,一种办法是在for 循环中对返回的键进行排序。为此,可使用函数sorted() 来获得按特定顺序排列的键列表的副本:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
for name in sorted(favorite_languages.keys()):
print(f"{name.title()}, thank you for taking the poll.")
这条for 语句类似于其他for 语句,不同之处是对方法dictionary.keys() 的结果调用了函数sorted() 。这让Python列出字典中的所有键,并在遍历前对这个列表进行排序。输出表明,按顺序显示了所有被调查者的名字:
Edward, thank you for taking the poll.
Jen, thank you for taking the poll.
Phil, thank you for taking the poll.
Sarah, thank you for taking the poll.
6.3.4 遍历字典中的所有值
如果主要对字典包含的值感兴趣,可使用方法values() 来返回一个值列表,不包含任何键。例如,假设我们想获得一个列表,其中只包含被调查者选择的各种语言,而不包含被调查者的名字,可以这样做:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
print("The following languages have been mentioned:")
for language in favorite_languages.values():
print(language.title())
这条for 语句提取字典中的每个值,并将其依次赋给变量language 。通过打印这些值,就获得了一个包含被调查者所选择语言的列表:
The following languages have been mentioned:
Python
C
Ruby
Python
这种做法提取字典中所有的值,而没有考虑是否重复。涉及的值很少时,这也许不是问题,但如果被调查者很多,最终的列表可能包含大量重复项。为剔除重复项,可使用集合(set)。集合 中的每个元素都必须是独一无二的:
favorite_languages = {
—snip—
}
print("The following languages have been mentioned:")
❶ for language in set(favorite_languages.values()):
print(language.title())
通过对包含重复元素的列表调用set() ,可让Python找出列表中独一无二的元素,并使用这些元素来创建一个集合。❶处使用set() 来提取favorite_languages.values() 中不同的语言。
结果是一个不重复的列表,其中列出了被调查者提及的所有语言:
The following languages have been mentioned:
Python
C
Ruby
随着你更深入地学习Python,经常会发现它内置的功能可帮助你以希望的方式处理数据。
注意 可使用一对花括号直接创建集合,并在其中用逗号分隔元素:
>>> languages = {'python', 'ruby', 'python', 'c'}
>>> languages
{'ruby', 'python', 'c'}
集合和字典很容易混淆,因为它们都是用一对花括号定义的。当花括号内没有键值对时,定义的很可能是集合。不同于列表和字典,集合不会以特定的顺序存储元素。
动手试一试
练习6-4:词汇表2 现在你知道了如何遍历字典,可以整理为完成练习6-3而编写的代码,将其中的一系列函数调用print() 替换为一个遍历字典中键和值的循环。确定该循环正确无误后,再在词汇表中添加5个Python术语。当你再次运行这个程序时,这些新术语及其含义将自动包含在输出中。
练习6-5:河流 创建一个字典,在其中存储三条重要河流及其流经的国家。例如,一个键值对可能是'nile': 'egypt' 。
使用循环为每条河流打印一条消息,下面是一个例子。
The Nile runs through Egypt.
使用循环将该字典中每条河流的名字打印出来。
使用循环将该字典包含的每个国家的名字打印出来。
练习6-6:调查 在6.3.1节编写的程序favorite_languages.py中执行以下操作。
- 创建一个应该会接受调查的人员名单,其中有些人已包含在字典中,而其他人未包含在字典中。
- 遍历这个人员名单。对于已参与调查的人,打印一条消息表示感谢;对于还未参与调查的人,打印一条消息邀请他参加。