Python提供了另一种组合数据类型称为字典,它类似于列表,因为它是对象的集合。
以下是您将在本教程中学到的内容:您将了解 Python 字典的基本特征,并学习如何访问和管理字典数据。完成本教程后,您应该很好地了解什么时候字典是适合使用的数据类型以及如何使用。
字典和列表具有以下共同特征:
- 两者都是可变的。
- 两者都是动态的。它们可以根据需要增长和缩小。
- 两者都可以嵌套。一个列表可以包含另一个列表。一个字典可以包含另一个字典。字典也可以包含列表,反之亦然。
字典与列表的主要区别在于元素的访问方式:
- 列表元素通过索引在列表中的位置进行访问。
- 字典元素通过键访问。
参加测验:通过我们的交互式“Python 词典”测验来测试您的知识。完成后,您将收到一个分数,以便您可以跟踪一段时间内的学习进度:
参加测验 »
定义字典
字典是 Python 的数据结构实现,通常称为关联数组。字典由键值对的集合组成。每个键值对将键映射到其关联的值。
您可以通过将逗号分隔的键值对列表括在大括号 ({}
)。冒号(:
) 将每个键与其关联的值分开:
d = {
<key>: <value>,
<key>: <value>,
.
.
.
<key>: <value>
}
下面定义了一个字典,将位置映射到其相应的美国职业棒球大联盟球队的名称:
>>>>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }
您还可以使用内置的字典构建字典dict()
功能。论点为dict()
应该是一系列键值对。元组列表非常适合此目的:
d = dict([
(<key>, <value>),
(<key>, <value),
.
.
.
(<key>, <value>)
])
MLB_team
那么也可以这样定义:
>>>>>> MLB_team = dict([
... ('Colorado', 'Rockies'),
... ('Boston', 'Red Sox'),
... ('Minnesota', 'Twins'),
... ('Milwaukee', 'Brewers'),
... ('Seattle', 'Mariners')
... ])
如果键值是简单字符串,则可以将它们指定为关键字参数。所以这里还有另一种定义方式MLB_team
:
>>>>>> MLB_team = dict(
... Colorado='Rockies',
... Boston='Red Sox',
... Minnesota='Twins',
... Milwaukee='Brewers',
... Seattle='Mariners'
... )
定义字典后,您可以显示其内容,就像显示列表一样。上面显示的所有三个定义在显示时如下所示:
>>>>>> type(MLB_team)
<class 'dict'>
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Mariners'}
字典中的条目按照定义的顺序显示。但这对于检索它们来说是无关紧要的。字典元素不通过数字索引访问:
>>>>>> MLB_team[1]
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
MLB_team[1]
KeyError: 1
也许你仍然想对你的字典进行排序。如果是这样的话,请检查一下对 Python 字典进行排序:值、键等.
访问字典值
当然,字典元素必须能够以某种方式访问。如果你不通过索引获取它们,那么如何获取它们呢?
通过在方括号中指定相应的键([]
):
>>>>>> MLB_team['Minnesota']
'Twins'
>>> MLB_team['Colorado']
'Rockies'
如果引用不在字典中的键,Python 会引发异常:
>>>>>> MLB_team['Toronto']
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
MLB_team['Toronto']
KeyError: 'Toronto'
向现有字典添加条目只需分配新的键和值:
>>>>>> MLB_team['Kansas City'] = 'Royals'
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Mariners', 'Kansas City': 'Royals'}
如果要更新条目,只需为现有键分配新值即可:
>>>>>> MLB_team['Seattle'] = 'Seahawks'
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Seahawks', 'Kansas City': 'Royals'}
要删除条目,请使用删除语句,指定要删除的键:
>>>>>> del MLB_team['Seattle']
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Kansas City': 'Royals'}
滚吧,海鹰!你是一支 NFL 球队。
字典键与列表索引
您可能已经注意到解释器引发了相同的异常,按键错误,当使用未定义的键或数字索引访问字典时:
>>>>>> MLB_team['Toronto']
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
MLB_team['Toronto']
KeyError: 'Toronto'
>>> MLB_team[1]
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
MLB_team[1]
KeyError: 1
事实上,这是同样的错误。在后一种情况下,[1]
看起来像一个数字索引,但事实并非如此。
您将在本教程后面看到任何对象不可变的type 可以用作字典键。因此,没有理由不能使用整数:
>>>>>> d = {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
>>> d
{0: 'a', 1: 'b', 2: 'c', 3: 'd'}
>>> d[0]
'a'
>>> d[2]
'c'
在表达式中MLB_team[1]
, d[0]
, 和d[2]
,方括号中的数字看起来就像是索引。但它们与字典中项目的顺序无关。 Python 将它们解释为字典键。如果以相反的顺序定义相同的字典,您仍然使用相同的键获得相同的值:
>>>>>> d = {3: 'd', 2: 'c', 1: 'b', 0: 'a'}
>>> d
{3: 'd', 2: 'c', 1: 'b', 0: 'a'}
>>> d[0]
'a'
>>> d[2]
'c'
语法可能看起来很相似,但你不能将字典视为列表:
>>>>>> type(d)
<class 'dict'>
>>> d[-1]
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
d[-1]
KeyError: -1
>>> d[0:2]
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
d[0:2]
TypeError: unhashable type: 'slice'
>>> d.append('e')
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
d.append('e')
AttributeError: 'dict' object has no attribute 'append'
笔记:尽管对字典中项目的访问不依赖于顺序,但 Python 确实保证保留字典中项目的顺序。显示时,项目将按其定义的顺序显示,并且按键的迭代也将按该顺序进行。添加到字典中的项目添加在最后。如果删除项目,则保留剩余项目的顺序。
您只能指望最近才能保持订单。它是在 3.7 版本中作为 Python 语言规范的一部分添加。然而,从 3.6 版开始也是如此——由于实现的偶然性,但语言规范并不能保证这一点。
增量构建字典
如果您事先知道所有键和值,那么使用大括号和键值对列表定义字典(如上所示)就可以了。但是如果您想即时构建字典怎么办?
您可以首先创建一个空字典,该字典由空花括号指定。然后您可以一次添加一个新的键和值:
>>>>>> person = {}
>>> type(person)
<class 'dict'>
>>> person['fname'] = 'Joe'
>>> person['lname'] = 'Fonebone'
>>> person['age'] = 51
>>> person['spouse'] = 'Edna'
>>> person['children'] = ['Ralph', 'Betty', 'Joey']
>>> person['pets'] = {'dog': 'Fido', 'cat': 'Sox'}
一旦以这种方式创建字典,其值的访问方式与任何其他字典相同:
>>>>>> person
{'fname': 'Joe', 'lname': 'Fonebone', 'age': 51, 'spouse': 'Edna',
'children': ['Ralph', 'Betty', 'Joey'], 'pets': {'dog': 'Fido', 'cat': 'Sox'}}
>>> person['fname']
'Joe'
>>> person['age']
51
>>> person['children']
['Ralph', 'Betty', 'Joey']
检索子列表或子字典中的值需要额外的索引或键:
>>>>>> person['children'][-1]
'Joey'
>>> person['pets']['cat']
'Sox'
这个例子展示了字典的另一个特性:字典中包含的值不需要是相同的类型。在person
,一些值是字符串,一个是整数,一个是列表,一个是另一个字典。
正如字典中的值不需要是同一类型一样,键也不需要是同一类型:
>>>>>> foo = {42: 'aaa', 2.78: 'bbb', True: 'ccc'}
>>> foo
{42: 'aaa', 2.78: 'bbb', True: 'ccc'}
>>> foo[42]
'aaa'
>>> foo[2.78]
'bbb'
>>> foo[True]
'ccc'
这里,其中一个键是整数,一个是浮点数,一个是布尔值。目前还不清楚这有什么用处,但你永远不知道。
请注意 Python 字典的多功能性。在MLB_team
,为每个不同的地理位置保留同一条信息(棒球队名称)。person
另一方面,存储单个人的不同类型的数据。
您可以将字典用于多种用途,因为对允许的键和值的限制很少。但也有一些。继续阅读!
字典键的限制
几乎任何类型的值都可以用作 Python 中的字典键。您刚刚看到了这个示例,其中整数、浮点和布尔对象用作键:
>>>>>> foo = {42: 'aaa', 2.78: 'bbb', True: 'ccc'}
>>> foo
{42: 'aaa', 2.78: 'bbb', True: 'ccc'}
您甚至可以使用内置对象,例如类型和函数:
>>>>>> d = {int: 1, float: 2, bool: 3}
>>> d
{<class 'int'>: 1, <class 'float'>: 2, <class 'bool'>: 3}
>>> d[float]
2
>>> d = {bin: 1, hex: 2, oct: 3}
>>> d[oct]
3
但是,字典键必须遵守一些限制。
首先,给定的键只能在字典中出现一次。不允许有重复的密钥。字典将每个键映射到相应的值,因此多次映射特定键是没有意义的。
您在上面看到,当您将值分配给已经存在的字典键时,它不会再次添加该键,而是替换现有值:
>>>>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }
>>> MLB_team['Minnesota'] = 'Timberwolves'
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Timberwolves',
'Milwaukee': 'Brewers', 'Seattle': 'Mariners'}
同样,如果在初始创建字典期间第二次指定某个键,则第二次出现的情况将覆盖第一次出现的情况:
>>>>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Timberwolves',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners',
... 'Minnesota': 'Twins'
... }
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Mariners'}
走吧,森林狼!你是一支 NBA 球队。有点。
其次,字典键必须是不可变的类型。您已经看到过一些示例,其中您熟悉的几种不可变类型(整数、浮点数、字符串和布尔值)已用作字典键。
元组也可以是字典键,因为元组是不可变的:
>>>>>> d = {(1, 1): 'a', (1, 2): 'b', (2, 1): 'c', (2, 2): 'd'}
>>> d[(1,1)]
'a'
>>> d[(2,1)]
'c'
(回想一下关于元组使用元组而不是列表的一个理由是,在某些情况下需要不可变类型。这是其中之一。)
但是,列表或其他字典都不能充当字典键,因为列表和字典是可变的:
>>>>>> d = {[1, 1]: 'a', [1, 2]: 'b', [2, 1]: 'c', [2, 2]: 'd'}
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
d = {[1, 1]: 'a', [1, 2]: 'b', [2, 1]: 'c', [2, 2]: 'd'}
TypeError: unhashable type: 'list'
技术说明:为什么错误消息显示“不可散列”?
从技术上讲,说对象必须是不可变的才能用作字典键并不完全正确。更准确地说,一个对象必须是可散列的,这意味着它可以传递给哈希函数。 A哈希函数获取任意大小的数据并将其映射到一个相对简单的固定大小值,称为哈希值(或简称散列),用于表查找和比较。
Python 的内置hash()
函数返回可哈希对象的哈希值,并对不可哈希的对象引发异常:
>>>>>> hash('foo')
11132615637596761
>>> hash([1, 2, 3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
到目前为止,您所了解的所有内置不可变类型都是可哈希的,而可变容器类型(列表和字典)则不是。因此,就目前的目的而言,您可以将可散列和不可变视为或多或少的同义词。
在以后的教程中,您将遇到也是可哈希的可变对象。
对字典值的限制
相比之下,字典值没有限制。从字面上看,根本没有。字典值可以是 Python 支持的任何类型的对象,包括列表和字典等可变类型以及用户定义的对象,您将在后续教程中了解这些对象。
对于某个特定值在字典中多次出现也没有限制:
>>>>>> d = {0: 'a', 1: 'a', 2: 'a', 3: 'a'}
>>> d
{0: 'a', 1: 'a', 2: 'a', 3: 'a'}
>>> d[0] == d[1] == d[2]
True
运算符和内置函数
您已经熟悉了许多可用于的运算符和内置函数字符串, 列表, 和元组。其中一些也适用于字典。
例如,in
和not in
运营商返回True
或者False
根据指定的操作数是否作为字典中的键出现:
>>>>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }
>>> 'Milwaukee' in MLB_team
True
>>> 'Toronto' in MLB_team
False
>>> 'Toronto' not in MLB_team
True
您可以使用in
运算符与短路评估一起使用,以避免在尝试访问不在字典中的键时引发错误:
>>>>>> MLB_team['Toronto']
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
MLB_team['Toronto']
KeyError: 'Toronto'
>>> 'Toronto' in MLB_team and MLB_team['Toronto']
False
在第二种情况下,由于短路评估,表达式MLB_team['Toronto']
没有被评估,所以KeyError
不会发生异常。
这len()
函数返回字典中键值对的数量:
>>>>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }
>>> len(MLB_team)
5
内置字典方法
与字符串和列表一样,有几个可以在字典上调用的内置方法。事实上,在某些情况下,列表和字典方法共享相同的名称。 (在面向对象编程的讨论中,您将看到不同类型具有相同名称的方法是完全可以接受的。)
以下是适用于字典的方法的概述:
d.clear()
清除字典。
d.clear()
清空字典d
所有键值对:
>>>>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> d.clear()
>>> d
{}
d.get(<key>[, <default>])
如果字典中存在键,则返回该键的值。
Python 字典.get()
方法提供了一种从字典中获取键值的便捷方法,无需提前检查键是否存在,也不会引发错误。
d.get(<key>)
搜索词典d
为了<key>
如果找到则返回关联值。如果<key>
没有找到,就返回None
:
>>>>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> print(d.get('b'))
20
>>> print(d.get('z'))
None
If <key>
未找到且可选<default>
指定了参数,则返回该值而不是None
:
>>>>>> print(d.get('z', -1))
-1
d.items()
返回字典中键值对的列表。
d.items()
返回包含键值对的元组列表d
。每个元组中的第一项是键,第二项是键的值:
>>>>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> list(d.items())
[('a', 10), ('b', 20), ('c', 30)]
>>> list(d.items())[1][0]
'b'
>>> list(d.items())[1][1]
20
d.keys()
返回字典中的键列表。
d.keys()
返回所有键的列表d
:
>>>>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> list(d.keys())
['a', 'b', 'c']
d.values()
返回字典中的值列表。
d.values()
返回所有值的列表d
:
>>>>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> list(d.values())
[10, 20, 30]
中的任何重复值d
将被返回任意多次:
>>>>>> d = {'a': 10, 'b': 10, 'c': 10}
>>> d
{'a': 10, 'b': 10, 'c': 10}
>>> list(d.values())
[10, 10, 10]
技术说明:这.items()
, .keys()
, 和.values()
方法实际上返回一个叫做 a 的东西查看对象。字典视图对象或多或少类似于键和值的窗口。出于实际目的,您可以将这些方法视为返回字典的键和值的列表。
d.pop(<key>[, <default>])
从字典中删除键(如果存在)并返回其值。
If <key>
存在于d
, d.pop(<key>)
删除<key>
并返回其关联值:
>>>>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.pop('b')
20
>>> d
{'a': 10, 'c': 30}
d.pop(<key>)
提出一个KeyError
异常如果<key>
不在d
:
>>>>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.pop('z')
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
d.pop('z')
KeyError: 'z'
If <key>
不在d
,以及可选的<default>
指定参数,然后返回该值,并且不会引发异常:
>>>>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.pop('z', -1)
-1
>>> d
{'a': 10, 'b': 20, 'c': 30}
d.popitem()
从字典中删除键值对。
d.popitem()
删除最后添加的键值对d
并将其作为元组返回:
>>>>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.popitem()
('c', 30)
>>> d
{'a': 10, 'b': 20}
>>> d.popitem()
('b', 20)
>>> d
{'a': 10}
If d
是空的,d.popitem()
提出一个KeyError
例外:
>>>>>> d = {}
>>> d.popitem()
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
d.popitem()
KeyError: 'popitem(): dictionary is empty'
笔记:在低于 3.6 的 Python 版本中,popitem()
将返回任意(随机)键值对,因为Python 字典是无序的3.6版本之前。
d.update(<obj>)
将字典与另一个字典或可迭代的键值对合并。
If <obj>
是一本字典,d.update(<obj>)
合并条目<obj>
进入d
。对于每个键<obj>
:
- 如果密钥不存在于
d
,键值对来自<obj>
被添加到d
.
- 如果密钥已经存在于
d
,对应的值在d
因为该键已更新为值<obj>
.
这是一个显示两个字典合并在一起的示例:
>>>>>> d1 = {'a': 10, 'b': 20, 'c': 30}
>>> d2 = {'b': 200, 'd': 400}
>>> d1.update(d2)
>>> d1
{'a': 10, 'b': 200, 'c': 30, 'd': 400}
在此示例中,键'b'
已经存在于d1
,因此其值更新为200
,该键的值来自d2
。然而,没有钥匙'd'
在d1
,因此键值对是从d2
.
<obj>
也可以是一系列键值对,类似于dict()
函数用于定义字典。例如,<obj>
可以指定为元组列表:
>>>>>> d1 = {'a': 10, 'b': 20, 'c': 30}
>>> d1.update([('b', 200), ('d', 400)])
>>> d1
{'a': 10, 'b': 200, 'c': 30, 'd': 400}
或者可以将要合并的值指定为关键字参数列表:
>>>>>> d1 = {'a': 10, 'b': 20, 'c': 30}
>>> d1.update(b=200, d=400)
>>> d1
{'a': 10, 'b': 200, 'c': 30, 'd': 400}
结论
在本教程中,您介绍了 Python 的基本属性字典并学习了如何访问和操作字典数据。
列表和字典是两种最常用的 Python 类型。正如您所看到的,它们有一些相似之处,但其元素的访问方式有所不同。列表元素通过基于顺序的数字索引来访问,字典元素通过键来访问
由于这种差异,列表和字典往往适合不同的情况。您现在应该有一个良好的感觉,如果有的话,对于给定的情况来说是最好的。
接下来你将学习Python套。集合是另一种复合数据类型,但它与列表或字典有很大不同。
参加测验:通过我们的交互式“Python 词典”测验来测试您的知识。完成后,您将收到一个分数,以便您可以跟踪一段时间内的学习进度:
参加测验 »
« Python 中的列表和元组
Python 中的集合 »