首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

RealPython 基础教程:Python 字典用法详解

在连续编写了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 以冒号来分隔。

其形式为:

下边我们定义一个 dict,用以存储美国职业棒球队联盟的信息。这个 dict 将各球队所属的地区映射到队名上。

可以用下图直观地表示这个映射结构:

还可以使用内置的 dict() 函数来创建一个 dict 对象。传入 dict() 函数的参数应该是一个包含 key-value 键值对的序列,比如由 tuple 对象组成的 list。

这种创建方法形式如下:

那么,上文中的 MLB_team 也可以采用这种方法来定义:

如果 key 的值是简单的字符串,它们可被指定为 dict() 函数的关键字参数。

这样,又有了一种定义 MLB_team 的方式:

一旦 dict 对象被定义,你就可以像 list 那样显示其中的内容。上述三种定义方式显示效果是一致的:

我们看到,dict 中的元素按其定义时的顺序显示了出来。但是,这不意味着你就可以按照这个顺序(索引)来依次获取这些元素。dict 中的元素不是通过数值索引来访问的。

【访问 dict 中的元素】

那么,我们该如何访问 dict 中的元素呢?

答案是:通过在中括号([])中指定元素的 key 来从 dict 中获取与 key 对应的 value 值。

如果 key 不存在于 dict 中,Python 会抛出异常:

向 dict 中添加元素的方法很简单,只需要执行一个键值对赋值操作就行了。

如果想更新 dict 中的元素,只需要为 key 赋一个新的 value 就行了。

可以通过 del 语句来删除 dict 中的元素,你需要在 del 后指定要删除的那个 key。

【对比 dict 键值和 list 索引】

在上边的例子中,如果 key 不存在于 dict,或使用数值索引来访问 dict 中的元素,Python 解释器都会抛出一个 KeyError 的异常。

这两个错误实际是同一个错误。[1] 这种形式看似是数值索引,但实际上并非如此。

本文后边会提到:任何一个不可变类型的对象都可以作为 dict 的 key。整数也可以。

这里,d[0] 和 d[2] 中的 0 和 2 看似索引,但它们与元素在 dict 中的位置顺序毫无关系。Python 将其解释为 dict 的 key。

如果你倒序定义上边这个 d,你再使用同样的 key 来访问,得到的值仍是相同的。

通过 key 来访问 dict 元素和通过索引来访问 list 中的元素,二者语法相似,但是你却不可以像 list 那样来操作 dict。

dict 不支持索引、切片和 append 这些访问和操作方法!

虽然不能通过位置顺序(索引)来访问 dict 中的元素,Python 却可以保证 dict 中元素的顺序按它们被定义时的那样得以保留。

定义时是什么顺序,输出时就是什么顺序。

新的元素会被“添加到尾部”。

删除一个元素后,剩余元素仍保持原来的顺序。

需要注意:dict 的这个特性仅在 Python 3.6 之后的版本支持。

【渐进式构建一个 dict】

如果我们已经提前知道了所有的 key 和 value,就可以使用大括号或者键值对序列的方式来定义 dict。但如果你想动态创建一个 dict,那该怎么办?

你可以先创建一个空的 dict,然后逐个添加新的 key 和 value。

以这种方式创建的 dict,其访问方式和其他方式创建的 dict 是一样的。

你需要使用额外的索引或 key 来访问 dict 中的子 list 或 子 dict 中的值。

这个例子展示了 dict 的另一特征:dict 中的 value 可不必是相同类型。person 中,某些 value 是字符串,一个 value 是整数,一个 value 是 list,还有一个 value 是另一个 dict。

与之相似,dict 中的 key 也不必是相同类型。

dict 元素的 key 和 value 上的限制如此之少,使得它具有非常广泛的用途。

【dict 键值(key)的使用约束】

虽然几乎任何类型的值都可用作 dict 的 key,但是对于 key 的使用,还是存在一些约束条件。

首先,dict 中不能存在重复的 key。每个 key 对应于一个 value。如果将 value 赋值给一个已存在的 key,它会替换原来的 value。

同样,如果你在初始化 dict 时两次使用了同一个 key,后者将会覆盖前者。

其次,dict 中的 key 必须属于不可变类型。

我们在上边的例子中已看到,像整数、浮点数、字符串、布尔值这些不可变类型值都可用作 key。

tuple 也可用作 dict 的 key,因为它也是不可变的。

而 list 和 dict 不可用作 key,因为这两者都是可变数据类型。

这里,我们看到报错提示:unhashable type。为什么会有这样的报错?

技术上讲,用作 dict 的 key 的对象必须是不可变类型,这句话并不十分正确。更精确的说法是:用作 key 的对象必须是可哈希的(hashable)。它可以传递给一个哈希函数,从而能够计算出一个可用来查表和比对的哈希值。

Python 内置的 hash() 函数返回一个可哈希对象的哈希值,如果此对象不可哈希,hash() 函数会抛出异常。

Python 中所有内置的不可变类型都是可哈希的,list 和 dict 这些可变的容器类型则不可哈希。

但是,我们以后会遇到可哈希的可变类型对象。这是后话,按下不表。

【dict 元素值(value)的使用约束】

dict 中 value 的类型约束很简单:没有限制!

任何类型的对象都可用作 dict 的 value。

【适用于 dict 的运算符和内置函数】

我们已经熟悉了许多运算符和内置函数,它们可用于字符串、list 和 tuple 对象上。有些也适用于 dict。

in 和 not in 可用于测试给定的 key 是否存在于 dict 中。

如果访问 dict 中不存在的 key,Python 会抛出异常。我们可以在短路求值中使用 in 来避免异常的发生。

len() 函数可用来计算 dict 中键值对的个数。

【dict 内置方法】

我们简单列举一下 dict 提供的一些内置方法。

d.clear(): 清空一个 dict 对象。

d.get([, ]):若 key 存在于 dict 中,返回其 value,否则返回 default 指定的值。

d.items():返回一个包含 dict 中键值对(key, value,)的 list。

d.keys():返回一个包含 dict 中所有 key 的 list。

d.valus():返回一个包含 dict 中所有 value 的 list。

注意:items()、key() 和 values() 返回的是一个称为 view 的对象,你需要使用 list() 将其转换为 list。

d.pop([, ]):从 dict 中删除 key 指定的元素,并返回其 value。若 key 不存在:若 指定了 default,则返回 default;否则抛出异常。

d.popitem():删除 dict 中最后添加的元素,并以 tuple 的形式将其返回。若 dict 为空,抛出异常。

d.update():将 obj 合并到 dict 中。

obj 可以是一个 dict 或一个包含键值对的序列。

被合并的值也可以是关键字参数列表。

合并算法为:若原 dict 中不存在 obj 中的 key,则将 obj 中的 key-value 添加到原 dict;若存在,则 obj 中的 key-value 会覆盖原 dict 中的 key-value。

温馨提示:

1. 我们后续将尝试从 Python 源码层面探索 dict 的底层数据结构和相关算法,敬请关注。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20210323A0161G00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券