RealPython 基础教程:Python 字典用法详解
liuian 2024-11-28 00:42 71 浏览
在连续编写了5篇和 list 相关的文章之后,我们继续《RealPython 基础教程》这个系列。
今天,我们要学习的数据结构是字典(dict)。
dict 是一个包含若干对象的集合。它和 list 有以下共同的特征:
- 它们都是可变的
- 它们都是动态的,可根据需要自行伸缩大小。
- 它们都可以嵌套使用。一个 list 可包含另一个 list,一个 dict 也可以包含另一个 dict。dict 也可以包含 list 等其他对象。
当然,dict 和 list 也是有很大区别的。
- list 中的元素是通过其位置索引来访问的
- dict 中的元素则是通过键值(key)来访问的
我们接下来详细了解一下 dict 的用法、特性和使用限制。
【定义一个 dict】
字典是 Python 语言对关联数组这种数据结构的实现。一个 dict 由一组键值对(key-value)组成。每个键值对可将 key 映射到和它关联的 value 上。
我们可以通过使用大括号({})包含一系列以逗号分隔的键值对来定义一个 dict。键值对中的 key 和 value 以冒号来分隔。
其形式为:
d = {
<key>: <value>,
<key>: <value>,
.
.
.
<key>: <value>
}下边我们定义一个 dict,用以存储美国职业棒球队联盟的信息。这个 dict 将各球队所属的地区映射到队名上。
>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }可以用下图直观地表示这个映射结构:
还可以使用内置的 dict() 函数来创建一个 dict 对象。传入 dict() 函数的参数应该是一个包含 key-value 键值对的序列,比如由 tuple 对象组成的 list。
这种创建方法形式如下:
d = dict([
(<key>, <value>),
(<key>, <value),
.
.
.
(<key>, <value>)
])那么,上文中的 MLB_team 也可以采用这种方法来定义:
>>> MLB_team = dict([
... ('Colorado', 'Rockies'),
... ('Boston', 'Red Sox'),
... ('Minnesota', 'Twins'),
... ('Milwaukee', 'Brewers'),
... ('Seattle', 'Mariners')
... ])如果 key 的值是简单的字符串,它们可被指定为 dict() 函数的关键字参数。
这样,又有了一种定义 MLB_team 的方式:
>>> MLB_team = dict(
... Colorado='Rockies',
... Boston='Red Sox',
... Minnesota='Twins',
... Milwaukee='Brewers',
... Seattle='Mariners'
... )一旦 dict 对象被定义,你就可以像 list 那样显示其中的内容。上述三种定义方式显示效果是一致的:
>>> type(MLB_team)
<class 'dict'>
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Mariners'}我们看到,dict 中的元素按其定义时的顺序显示了出来。但是,这不意味着你就可以按照这个顺序(索引)来依次获取这些元素。dict 中的元素不是通过数值索引来访问的。
>>> MLB_team[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 1【访问 dict 中的元素】
那么,我们该如何访问 dict 中的元素呢?
答案是:通过在中括号([])中指定元素的 key 来从 dict 中获取与 key 对应的 value 值。
>>> MLB_team['Minnesota']
'Twins'
>>> MLB_team['Colorado']
'Rockies'如果 key 不存在于 dict 中,Python 会抛出异常:
>>> MLB_team['Toronto']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Toronto'向 dict 中添加元素的方法很简单,只需要执行一个键值对赋值操作就行了。
>>> MLB_team['Kansas City'] = 'Royals'
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Mariners', 'Kansas City': 'Royals'}如果想更新 dict 中的元素,只需要为 key 赋一个新的 value 就行了。
>>> MLB_team['Seattle'] = 'Seahawks'
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Seahawks', 'Kansas City': 'Royals'}可以通过 del 语句来删除 dict 中的元素,你需要在 del 后指定要删除的那个 key。
>>> del MLB_team['Seattle']
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Kansas City': 'Royals'}【对比 dict 键值和 list 索引】
在上边的例子中,如果 key 不存在于 dict,或使用数值索引来访问 dict 中的元素,Python 解释器都会抛出一个 KeyError 的异常。
>>> MLB_team['Toronto']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Toronto'
>>>
>>> MLB_team[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 1这两个错误实际是同一个错误。[1] 这种形式看似是数值索引,但实际上并非如此。
本文后边会提到:任何一个不可变类型的对象都可以作为 dict 的 key。整数也可以。
>>> d = {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
>>> d
{0: 'a', 1: 'b', 2: 'c', 3: 'd'}
>>>
>>> d[0]
'a'
>>> d[2]
'c'这里,d[0] 和 d[2] 中的 0 和 2 看似索引,但它们与元素在 dict 中的位置顺序毫无关系。Python 将其解释为 dict 的 key。
如果你倒序定义上边这个 d,你再使用同样的 key 来访问,得到的值仍是相同的。
>>> d = {3: 'd', 2: 'c', 1: 'b', 0: 'a'}
>>> d
{3: 'd', 2: 'c', 1: 'b', 0: 'a'}
>>> d[0]
'a'
>>> d[2]
'c'通过 key 来访问 dict 元素和通过索引来访问 list 中的元素,二者语法相似,但是你却不可以像 list 那样来操作 dict。
>>> d = {3: 'd', 2: 'c', 1: 'b', 0: 'a'}
>>> type(d)
<class 'dict'>
>>>
>>> d[-1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: -1
>>>
>>> d[0:2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'slice'
>>>
>>> d.append('e')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'append'dict 不支持索引、切片和 append 这些访问和操作方法!
虽然不能通过位置顺序(索引)来访问 dict 中的元素,Python 却可以保证 dict 中元素的顺序按它们被定义时的那样得以保留。
>>> d = {3: 'd', 2: 'c', 1: 'b', 0: 'a'}
>>> d
{3: 'd', 2: 'c', 1: 'b', 0: 'a'}
>>> d[-1] = 'e'
>>> d
{3: 'd', 2: 'c', 1: 'b', 0: 'a', -1: 'e'}
>>> d[5] = 'f'
>>> d
{3: 'd', 2: 'c', 1: 'b', 0: 'a', -1: 'e', 5: 'f'}
>>>
>>> del d[1]
>>> d
{3: 'd', 2: 'c', 0: 'a', -1: 'e', 5: 'f'}定义时是什么顺序,输出时就是什么顺序。
新的元素会被“添加到尾部”。
删除一个元素后,剩余元素仍保持原来的顺序。
需要注意:dict 的这个特性仅在 Python 3.6 之后的版本支持。
【渐进式构建一个 dict】
如果我们已经提前知道了所有的 key 和 value,就可以使用大括号或者键值对序列的方式来定义 dict。但如果你想动态创建一个 dict,那该怎么办?
你可以先创建一个空的 dict,然后逐个添加新的 key 和 value。
>>> 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'}以这种方式创建的 dict,其访问方式和其他方式创建的 dict 是一样的。
>>> 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']你需要使用额外的索引或 key 来访问 dict 中的子 list 或 子 dict 中的值。
>>> person['children'][-1]
'Joey'
>>> person['pets']['cat']
'Sox'这个例子展示了 dict 的另一特征:dict 中的 value 可不必是相同类型。person 中,某些 value 是字符串,一个 value 是整数,一个 value 是 list,还有一个 value 是另一个 dict。
与之相似,dict 中的 key 也不必是相同类型。
>>> 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'dict 元素的 key 和 value 上的限制如此之少,使得它具有非常广泛的用途。
【dict 键值(key)的使用约束】
虽然几乎任何类型的值都可用作 dict 的 key,但是对于 key 的使用,还是存在一些约束条件。
首先,dict 中不能存在重复的 key。每个 key 对应于一个 value。如果将 value 赋值给一个已存在的 key,它会替换原来的 value。
>>> 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'}同样,如果你在初始化 dict 时两次使用了同一个 key,后者将会覆盖前者。
... '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'}其次,dict 中的 key 必须属于不可变类型。
我们在上边的例子中已看到,像整数、浮点数、字符串、布尔值这些不可变类型值都可用作 key。
tuple 也可用作 dict 的 key,因为它也是不可变的。
>>> d = {(1, 1): 'a', (1, 2): 'b', (2, 1): 'c', (2, 2): 'd'}
>>> d[(1,1)]
'a'
>>> d[(2,1)]
'c'而 list 和 dict 不可用作 key,因为这两者都是可变数据类型。
>>> d = {[1, 1]: 'a', [1, 2]: 'b', [2, 1]: 'c', [2, 2]: 'd'}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'这里,我们看到报错提示:unhashable type。为什么会有这样的报错?
技术上讲,用作 dict 的 key 的对象必须是不可变类型,这句话并不十分正确。更精确的说法是:用作 key 的对象必须是可哈希的(hashable)。它可以传递给一个哈希函数,从而能够计算出一个可用来查表和比对的哈希值。
Python 内置的 hash() 函数返回一个可哈希对象的哈希值,如果此对象不可哈希,hash() 函数会抛出异常。
>>> hash('foo')
-2375898492641405263
>>> hash([1, 2, 3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'Python 中所有内置的不可变类型都是可哈希的,list 和 dict 这些可变的容器类型则不可哈希。
但是,我们以后会遇到可哈希的可变类型对象。这是后话,按下不表。
【dict 元素值(value)的使用约束】
dict 中 value 的类型约束很简单:没有限制!
任何类型的对象都可用作 dict 的 value。
【适用于 dict 的运算符和内置函数】
我们已经熟悉了许多运算符和内置函数,它们可用于字符串、list 和 tuple 对象上。有些也适用于 dict。
in 和 not in 可用于测试给定的 key 是否存在于 dict 中。
... '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如果访问 dict 中不存在的 key,Python 会抛出异常。我们可以在短路求值中使用 in 来避免异常的发生。
>>> MLB_team['Toronto']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Toronto'
>>>
>>> 'Toronto' in MLB_team and MLB_team['Toronto']
Falselen() 函数可用来计算 dict 中键值对的个数。
>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }
>>> len(MLB_team)
5【dict 内置方法】
我们简单列举一下 dict 提供的一些内置方法。
d.clear(): 清空一个 dict 对象。
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> d.clear()
>>> d
{}d.get(<key>[, <default>]):若 key 存在于 dict 中,返回其 value,否则返回 default 指定的值。
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.get('b')
20
>>> d.get('z')
>>>
>>> d.get('z', -1)
-1d.items():返回一个包含 dict 中键值对(key, value,)的 list。
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> d.items()
dict_items([('a', 10), ('b', 20), ('c', 30)])
>>>
>>> list(d.items())
[('a', 10), ('b', 20), ('c', 30)]
>>> list(d.items())[1][0]
'b'd.keys():返回一个包含 dict 中所有 key 的 list。
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> list(d.keys())
['a', 'b', 'c']d.valus():返回一个包含 dict 中所有 value 的 list。
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> list(d.values())
[10, 20, 30]注意:items()、key() 和 values() 返回的是一个称为 view 的对象,你需要使用 list() 将其转换为 list。
d.pop(<key>[, <default>]):从 dict 中删除 key 指定的元素,并返回其 value。若 key 不存在:若 指定了 default,则返回 default;否则抛出异常。
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.pop('b')
20
>>> d
{'a': 10, 'c': 30}
>>>
>>> d.pop('z')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'z'
>>>
>>> d.pop('z', -1)
-1
>>> d
{'a': 10, 'c': 30}d.popitem():删除 dict 中最后添加的元素,并以 tuple 的形式将其返回。若 dict 为空,抛出异常。
>>> d = {'a': 10, 'b': 20}
>>> d.popitem()
('b', 20)
>>> d.popitem()
('a', 10)
>>> d.popitem()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'popitem(): dictionary is empty'd.update(<obj>):将 obj 合并到 dict 中。
obj 可以是一个 dict 或一个包含键值对的序列。
>>> d1 = {'a': 10, 'b': 20, 'c': 30}
>>> d2 = {'b': 200, 'd': 400}
>>> d1.update(d2)
>>> 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}被合并的值也可以是关键字参数列表。
>>> d1 = {'a': 10, 'b': 20, 'c': 30}
>>> d1.update(b=200, d=400)
>>> d1
{'a': 10, 'b': 200, 'c': 30, 'd': 400}合并算法为:若原 dict 中不存在 obj 中的 key,则将 obj 中的 key-value 添加到原 dict;若存在,则 obj 中的 key-value 会覆盖原 dict 中的 key-value。
温馨提示:
1. 我们后续将尝试从 Python 源码层面探索 dict 的底层数据结构和相关算法,敬请关注。
2. 本文首发于微信公众号:python学与思。
python学与思分享优质原创 Python 教程和技术文章,整理 Python 常用库和开源框架的使用文档,汇集 Python 常见疑难问题解决方法。realpython.cn 和你一起学 Python!
【近期热门文章】
相关推荐
-
- 驱动网卡(怎么从新驱动网卡)
-
网卡一般是指为电脑主机提供有线无线网络功能的适配器。而网卡驱动指的就是电脑连接识别这些网卡型号的桥梁。网卡只有打上了网卡驱动才能正常使用。并不是说所有的网卡一插到电脑上面就能进行数据传输了,他都需要里面芯片组的驱动文件才能支持他进行数据传输...
-
2026-01-30 00:37 liuian
- win10更新助手装系统(微软win10更新助手)
-
1、点击首页“系统升级”的按钮,给出弹框,告诉用户需要上传IMEI码才能使用升级服务。同时给出同意和取消按钮。华为手机助手2、点击同意,则进入到“系统升级”功能华为手机助手华为手机助手3、在检测界面,...
- windows11专业版密钥最新(windows11专业版激活码永久)
-
Windows11专业版的正版密钥,我们是对windows的激活所必备的工具。该密钥我们可以通过微软商城或者通过计算机的硬件供应商去购买获得。获得了windows11专业版的正版密钥后,我...
-
- 手机删过的软件恢复(手机删除过的软件怎么恢复)
-
操作步骤:1、首先,我们需要先打开手机。然后在许多图标中找到带有[文件管理]文本的图标,然后单击“文件管理”进入页面。2、进入页面后,我们将在顶部看到一行文本:手机,最新信息,文档,视频,图片,音乐,收藏,最后是我们正在寻找的[更多],单击...
-
2026-01-29 23:55 liuian
- 一键ghost手动备份系统步骤(一键ghost 备份)
-
步骤1、首先把装有一键GHOST装系统的U盘插在电脑上,然后打开电脑马上按F2或DEL键入BIOS界面,然后就选择BOOT打USDHDD模式选择好,然后按F10键保存,电脑就会马上重启。 步骤...
- 怎么创建局域网(怎么创建局域网打游戏)
-
1、购买路由器一台。进入路由器把dhcp功能打开 2、购买一台交换机。从路由器lan端口拉出一条网线查到交换机的任意一个端口上。 3、两台以上电脑。从交换机任意端口拉出网线插到电脑上(电脑设置...
- 精灵驱动器官方下载(精灵驱动手机版下载)
-
是的。驱动精灵是一款集驱动管理和硬件检测于一体的、专业级的驱动管理和维护工具。驱动精灵为用户提供驱动备份、恢复、安装、删除、在线更新等实用功能。1、全新驱动精灵2012引擎,大幅提升硬件和驱动辨识能力...
- 一键还原系统步骤(一键还原系统有哪些)
-
1、首先需要下载安装一下Windows一键还原程序,在安装程序窗口中,点击“下一步”,弹出“用户许可协议”窗口,选择“我同意该许可协议的条款”,并点击“下一步”。 2、在弹出的“准备安装”窗口中,可...
- 电脑加速器哪个好(电脑加速器哪款好)
-
我认为pp加速器最好用,飞速土豆太懒,急速酷六根本不工作。pp加速器什么网页都加速,太任劳任怨了!以上是个人观点,具体性能请自己试。ps:我家电脑性能很好。迅游加速盒子是可以加速电脑的。因为有过之...
- 任何u盘都可以做启动盘吗(u盘必须做成启动盘才能装系统吗)
-
是的,需要注意,U盘的大小要在4G以上,最好是8G以上,因为启动盘里面需要装系统,内存小的话,不能用来安装系统。内存卡或者U盘或者移动硬盘都可以用来做启动盘安装系统。普通的U盘就可以,不过最好U盘...
- u盘怎么恢复文件(u盘文件恢复的方法)
-
开360安全卫士,点击上面的“功能大全”。点击文件恢复然后点击“数据”下的“文件恢复”功能。选择驱动接着选择需要恢复的驱动,选择接入的U盘。点击开始扫描选好就点击中间的“开始扫描”,开始扫描U盘数据。...
- 系统虚拟内存太低怎么办(系统虚拟内存占用过高什么原因)
-
1.检查系统虚拟内存使用情况,如果发现有大量的空闲内存,可以尝试释放一些不必要的进程,以释放内存空间。2.如果系统虚拟内存使用率较高,可以尝试增加系统虚拟内存的大小,以便更多的应用程序可以使用更多...
-
- 剪贴板权限设置方法(剪贴板访问权限)
-
1、首先打开iphone手机,触碰并按住单词或图像直到显示选择选项。2、其次,然后选取“拷贝”或“剪贴板”。3、勾选需要的“权限”,最后选择开启,即可完成苹果剪贴板权限设置。仅参考1.打开苹果手机设置按钮,点击【通用】。2.点击【键盘】,再...
-
2026-01-29 21:37 liuian
- 平板系统重装大师(平板重装win系统)
-
如果你的平板开不了机,但可以连接上电脑,那就能好办,楼主下载安装个平板刷机王到你的个人电脑上,然后连接你的平板,平板刷机王会自动识别你的平板,平板刷机王上有你平板的我刷机包,楼主点击下载一个,下载完成...
- 联想官网售后服务网点(联想官网售后服务热线)
-
联想3c服务中心是联想旗下的官方售后,是基于互联网O2O模式开发的全新服务平台。可以为终端用户提供多品牌手机、电脑以及其他3C类产品的维修、保养和保险服务。根据客户需求层次,联想服务针对个人及家庭客户...
- 一周热门
- 最近发表
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)
- c++ 字符串查找 (35)
- mysql刷新权限 (34)
