深入解析Python字典:创建、操作与迭代指南

凌晨两点半
凌晨两点半
发布时间:2026-10-12 | 2人浏览过
原创

本文深入探讨Python中的字典(dictionary)容器类型。文章详细讲解了字典的创建方法,包括使用花括号和构造函数,强调了键必须为不可变类型且值可为任意类型的特性。同时,介绍了字典的访问、修改、删除操作,以及利用keys()、values()和迭代器进行条件测试与遍历的高级技巧,帮助开发者高效掌握这一核心数据结构。

dictionary

我们日常使用语言词典来查询生僻词的定义。词典通过给定的单词(如python)提供标准化的信息,将定义及其他内容与单词本身关联(映射),利用单词作为键来定位感兴趣的信息。这一概念在Python编程语言中被扩展为一种特殊的容器类型,即字典(dictionary)。

字典数据类型广泛存在于多种编程语言中,有时被称为关联数组(因为数据与键关联)或散列表。但在Python中,字典是一种优秀的对象,即便是编程初学者也能轻松在程序中使用。从正式定义来看,Python中的字典是一种异构的、可变(易变)的映射容器数据类型。 创建字典

本系列前文介绍了Python中的其他容器数据类型,如元组(tuple)、字符串(string)和列表(list)。这些容器的共同点是它们都基于序列,即通过元素在序列中的位置来访问元素。因此,对于名为a的序列,可以使用数字索引(如a[0])或切片(如a[1:5])来访问元素。Python中的字典容器与前三种容器的不同之处在于,它是一个无序集合。它不是通过索引号,而是通过键值来访问集合中的元素。这意味着构建字典容器比元组、字符串或列表更复杂,因为必须同时提供键和相应的值,如清单1所示。 清单1. 在Python中创建字典,第1部分

>>> d = {0: 'zero', 1: 'one', 2 : 'two', 3 : 'three', 4 : 'four', 5: 'five'}
>>> d
{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}
>>> len(d)
>>> type(d)     # Base object is the dict class
<type 'dict'>
>>> d = {}      # Create an empty dictionary
>>> len(d)
>>> d = {1 : 'one'} # Create a single item dictionary
>>> d
{1: 'one'}
>>> len(d)
>>> d = {'one' : 1} # The key value can be non-numeric
>>> d
{'one': 1}
>>> d = {'one': [0, 1,2 , 3, 4, 5, 6, 7, 8, 9]}
>>> d
{'one': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}

如示例所示,在Python中创建字典需使用花括号和以冒号分隔的键-值对。若未提供键-值对,则创建一个空字典。提供一个键-值对,则创建包含一个元素的字典,依此类推,直至达到所需规模。与任何容器类型一样,可以使用内置的len方法查询集合中元素的数量。

前面的示例还展示了关于字典容器的另一个重要问题:键不限于整数;它可以是任何不可变的数据类型,包括整数、浮点数、元组或字符串。由于列表是可变(易变)的,因此它不能作为字典中的键。但是,字典中的值可以是任何数据类型的。

最后,该示例说明了Python中字典的底层数据类型是dict对象。要进一步了解如何在Python中使用字典,可以使用内置的帮助解释器来查看dict类,如清单2所示。 清单2. 获取关于字典的帮助

>>> help(dict)on class dict in module __builtin__:
   dict(object)
| dict() -> new empty dictionary.
| dict(mapping) -> new dictionary initialized from a mapping object's
|   (key, value) pairs.
| dict(seq) -> new dictionary initialized as if via:
|   d = {}
|   for k, v in seq:
|     d[k] = v
| dict(**kwargs) -> new dictionary initialized with the name=value pairs
|   in the keyword argument list. For example: dict(one=1, two=2)
| 
| Methods defined here:
| 
| __cmp__(...)
|   x.__cmp__(y) <==> cmp(x,y)
| 
| __contains__(...)
|   x.__contains__(y) <==> y in x
| 
| __delitem__(...)
|   x.__delitem__(y) <==> del x[y]
...

关于dict类的帮助指出,可以使用构造函数直接创建字典,而无需使用花括号。既然与其他容器数据类型相比,创建字典时需要提供更多数据,那么这些创建方法较为复杂也就不足为奇了。但在实践中使用字典并不困难,如清单3所示。 清单3. 在Python中创建字典,第2部分

>>> l = [0, 1,2 , 3, 4, 5, 6, 7, 8, 9] 
>>> d = dict(l)(most recent call last):
 File "<stdin>", line 1, in ?: can't convert dictionary 
 update sequence element #0 to a sequence
  
>>> l = [(0, 'zero'), (1, 'one'), (2, 'two'), (3, 'three')]
>>> d = dict(l)
>>> d
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> l = [[0, 'zero'], [1, 'one'], [2, 'two'], [3, 'three']]
>>> d
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> d = dict(l)
>>> d
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> d = dict(zero=0, one=1, two=2, three=3) 
>>> d
{'zero': 0, 'three': 3, 'two': 2, 'one': 1}
>>> d = dict(0=zero, 1=one, 2=two, 3=three): keyword can't be an expression

可以看到,创建字典需要键和对应的数据值。第一次尝试从列表创建字典失败了,因为没有匹配的键-数据值对。第二个和第三个示例演示了如何正确创建字典:在第一种情况下,使用一个列表,其中每个元素都是一个元组;在第二种情况下,也使用一个列表,但其中每个元素是另一个列表。在这两种情况下,内部容器都用于获取从键到数据值的映射。

直接创建dict容器的另一种方法是直接提供从键到数据值的映射。这种技术允许显式定义键及其对应的值。此方法其实用处不大,因为可以使用花括号完成相同的任务。另外,如前面的示例所示,在采用这种方式时若对键使用数字,会导致抛出异常。 访问和修改字典

创建字典后,需要访问其中包含的数据。访问方式与访问任何Python容器数据类型中的数据相似,如清单4所示。 清单4. 访问字典中的元素

>>> d = dict(zero=0, one=1, two=2, three=3)
>>> d
{'zero': 0, 'three': 3, 'two': 2, 'one': 1}
>>> d['zero']
>>> d['three']
>>> d = {0: 'zero', 1: 'one', 2 : 'two', 3 : 'three', 4 : 'four', 5: 'five'}
>>> d[0]
'zero'
>>> d[4]
'four'
>>> d[6](most recent call last):
 File "<stdin>", line 1, in ?: 6
>>> d[:-1](most recent call last):
 File "<stdin>", line 1, in ?: unhashable type

可以看到,从字典中获取数据值的过程几乎与从任何容器类型中获取数据完全一样。在容器名后的方括号中放入键值。当然,字典可以具有非数字的键值,如果您以前未使用过这种数据类型,适应这一点需要一些时间。因为在字典中顺序并不重要(字典中数据的顺序是任意的),所以其他容器数据类型使用的切片功能,对于字典是不可用的。试图使用切片或试图从不存在的键访问数据就会抛出异常,指出相关错误。

Python中的字典容器也是可变(易变)的数据类型,这意味着在创建它之后可以修改它。如清单5所示,可以添加新的键到数据值的映射,可以修改现有的映射,还可以删除映射。 清单5. 修改字典

>>> d = {0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> d[0]
'zero'
>>> d[0] = 'Zero'
>>> d
{0: 'Zero', 1: 'one', 2: 'two', 3: 'three'}
>>> d[4] = 'four'
>>> d[5] = 'five'
>>> d
{0: 'Zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}
>>> del d[0]
>>> d
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}
>>> d[0] = 'zero'
>>> d
{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}

清单5演示了几个重点。首先,修改数据值很简单:将新值分配给相应的键。其次,添加新的键到数据值的映射也很简单:将相关数据分配给新键值。Python自动处理所有操作,无需调用append等特殊方法。对于字典容器,顺序并不重要,因此这应该容易理解,因为不是在字典后面附加映射,而是将其添加到容器中。最后,删除映射的方法是使用del操作符以及应从容器中删除的键。

在清单5中有一个情况看起来有点奇怪,键值按照数字顺序显示,且该顺序与插入映射的顺序相同。请勿误解——情况并不总是如此。Python字典中映射的顺序是任意的,对于不同的Python安装可能会有所不同,甚至多次使用同一Python解释器运行相同代码也会有所不同。如果在字典中使用不同类型的键和数据值,就很容易看出这一点,如清单6所示。 清单6. 异构容器

>>> d = {0: 'zero', 'one': 1}   
>>> d
{0: 'zero', 'one': 1}
>>> d[0]
'zero'
>>> type(d[0])
<type 'str'>
>>> d['one']
>>> type(d['one'])
<type 'int'>
>>> d['two'] = [0, 1, 2] 
>>> d
{0: 'zero', 'two': [0, 1, 2], 'one': 1}
>>> d[3] = (0, 1, 2, 3)
>>> d
{0: 'zero', 3: (0, 1, 2, 3), 'two': [0, 1, 2], 'one': 1}
>>> d[3] = 'a tuple'
>>> d
{0: 'zero', 3: 'a tuple', 'two': [0, 1, 2], 'one': 1}

如该示例所示,可以在一个字典中使用不同数据类型的键和数据值。还可以通过修改字典添加新类型。最后,生成的字典的顺序与插入数据的顺序不匹配。本质上,字典中元素的顺序由Python字典数据类型的实际实现控制。新的Python解释器很容易改变这一顺序,因此切勿依赖元素在字典中的特定顺序。 用字典进行编程

作为正式的Python数据类型,字典支持其他较简单数据类型所支持的大多数操作。这些操作包括一般的关系运算符,如<、>和==,如清单7所示。 清单7. 一般关系运算符

>>> d1 = {0: 'zero'}
>>> d2 = {'zero':0}
>>> d1 < d2
>>> d2 = d1
>>> d1 < d2
>>> d1 == d2
>>> id(d1)
>>> id(d2)
>>> d2 = d1.copy()
>>> d1 == d2
>>> id(d1)
>>> id(d2)

前面的示例创建两个字典并使用它们测试<关系运算符。尽管很少以这种方式比较两个字典;但如果需要,可以这样做。

然后,该示例将赋值给变量d1的字典赋值给另一个变量d2。注意,内置的id()方法对于d1和d2返回相同的标识符值,这说明这不是复制操作。要想复制字典,可以使用copy()方法。从该示例中的最后几行可以看出,副本与原来的字典完全相同,但容纳该字典的变量具有不同的标识符。

在Python程序中使用字典时,很可能希望检查字典中是否包含特定的键或值。如清单8所示,这些检查很容易执行。 清单8. 条件测试和字典

>>> d = {0: 'zero', 3: 'a tuple', 'two': [0, 1, 2], 'one': 1}
>>> d.keys()
[0, 3, 'two', 'one']
>>> if 0 in d.keys():
...   print 'True'
... 
>>> if 'one' in d:
...   print 'True'
... 
>>> if 'four' in d:
...   print 'Dictionary contains four'
... elif 'two' in d:
...   print 'Dictionary contains two'
... contains two

测试字典中键或数据值的成员关系很简单。字典容器数据类型提供几个内置方法,包括keys()方法和values()方法(此处未演示)。这些方法返回一个列表,其中分别包含调用keys()或values()方法时字典中的键或数据值。

因此,要判断某个值是否是字典中的键,应使用in运算符检查该值是否在调用keys()方法所返回的键值列表中。可以使用相似的操作检查某个值是否在调用values()方法所返回的数据值列表中。但是,可以使用字典名作为简写表示法。这是有意义的,因为通常希望知道某个数据值(而非键值)是否在字典中。

在“Discover Python, Part 6”中,您看到了使用for循环遍历容器中的元素是多么容易。同样的技术也适用于Python字典,如清单9所示。 清单9. 迭代和字典

>>> d = {0: 'zero', 3: 'a tuple', 'two': [0, 1, 2], 'one': 1}
>>> for k in d.iterkeys():
...   print d[k]
... tuple
[0, 1, 2]
>>> for v in d.itervalues():
...   print v
... tuple
[0, 1, 2]
>>> for k, v in d.iteritems():
...   print 'd[',k,'] = ',v
... [ 0 ] = zero[ 3 ] = a tuple[ two ] = [0, 1, 2][ one ] = 1

该示例演示了遍历字典的三种方式:使用从iterkeys()、itervalues()或iteritems()方法返回的Python迭代器。(顺便说一下,可以通过在字典上直接调用适当方法,如d.iterkeys(),从而检查这些方法是否返回一个迭代器而非容器数据类型。)iterkeys()方法允许遍历字典的键,而itervalues()方法允许遍历字典包含的数据值。另一方面,iteritems()方法允许同时遍历键到数据值的映射。

字典:另一种强大的Python容器

本文讨论了Python字典数据类型。字典是一种异构的、可变(易变)的容器,依赖键到数据值的映射(而非特定的数字顺序)来访问容器中的元素。访问、添加和删除字典中的元素都很简单,而且字典很容易用于复合语句,如if语句或for循环。可以在字典中存储所有不同类型的数据,可以按照名称或其他复合键值(如元组)访问这些数据,因此Python字典使开发人员能够编写简洁而又强大的编程语句。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表