>>> from env_helper import info; info()
页面更新时间: 2020-02-29 10:55:17
操作系统/OS: Linux-4.19.0-8-amd64-x86_64-with-debian-10.3 ;Python: 3.7.3

5.2. 创建和使用字典

字典以类似于下面的方式表示:

>>> phonebook = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}

字典由键及其相应的值组成,这种键-值对称为项(item)。每个键与其值之间都用冒号 “:”分隔,项之间用逗号分隔,而整个字典放在花括号内。空字典“:”用两个花括号表示,类似于“{}”

注意 在字典(以及其他映射类型)中,键必须是独一无二的,而字典中的值无需如此。

5.2.1. 函数 dict

可使用函数 dict从其他映射(如其他字典)或键-值对序列创建字典。

>>> items = [('name', 'Gumby'), ('age', 42)]
>>> d = dict(items)
>>> d
{'name': 'Gumby', 'age': 42}
>>> d['name']
'Gumby'

还可使用关键字实参来调用这个函数,如下所示:

>>> d = dict(name='Gumby', age=42)
>>> d
{'name': 'Gumby', 'age': 42}

代码清单4-1列出了创建电话簿数据库的代码。

代码清单4-1 字典示例

>>> # 一个简单的数据库
>>> # 一个将人名用作键的字典。每个人都用一个字典表示,
>>> # 字典包含键'phone'和'addr',它们分别与电话号码和地址相关联
>>> people = {
>>>     'Alice': {
>>>     'phone': '2341',
>>>     'addr': 'Foo drive 23'
>>> },
>>> 'Beth': {
>>>     'phone': '9102',
>>>     'addr': 'Bar street 42'
>>> },
>>> 'Cecil': {
>>>     'phone': '3158',
>>>     'addr': 'Baz avenue 90'
>>> }
>>> }
>>> # 电话号码和地址的描述性标签,供打印输出时使用
>>> labels = {
>>>     'phone': 'phone number',
>>>     'addr': 'address'
>>> }
>>>
>>> name = input('Name: ')
>>> # 要查找电话号码还是地址?
>>> request = input('Phone number (p) or address (a)? ')
>>> # 使用正确的键:
>>> if request == 'p':
>>>     key = 'phone'
>>> if request == 'a':
>>>     key = 'addr'
>>> # 仅当名字是字典包含的键时才打印信息:
>>> if name in people:
>>>     print("{}'s {} is {}.".format(name, labels[key], people[name][key]))
Name: test
Phone number (p) or address (a)? 3158

5.2.2. 将字符串格式设置功能用于字典

在有些情况下,通过在字典中存储一系列命名的值,可让格式设置更容易些。例如,可在字典中包含各种信息,这样只需在格式字符串中提取所需的信息即可。为此,必须使用 format_map 来指出你将通过一个映射来提供所需的信息。

>>> phonebook
{'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
>>> "Cecil's phone number is {Cecil}.".format_map(phonebook)
"Cecil's phone number is 3258."

像这样使用字典时,可指定任意数量的转换说明符,条件是所有的字段名都是包含在字典中 的键。在模板系统中,这种字符串格式设置方式很有用(下面的示例使用的是HTML)。

>>> template = '''<html>
>>> <head><title>{title}</title></head>
>>> <body>
>>> <h1>{title}</h1>
>>> <p>{text}</p>
>>> ... </body>'''
>>> data = {'title': 'My Home Page', 'text': 'Welcome to my home page!'}
>>> print(template.format_map(data))
<html>
<head><title>My Home Page</title></head>
<body>
<h1>My Home Page</h1>
<p>Welcome to my home page!</p>
... </body>

5.2.3. 字典方法

clear方法

clear删除所有的字典项,这种操作是就地执行的,因此什么都不返回(或者说返回 None )。

>>> d = {}
>>> d['name'] = 'Gumby'
>>> d['age'] = 42
>>> d
{'name': 'Gumby', 'age': 42}
>>> returned_value = d.clear()
>>> d
{}
>>> print(returned_value)
None

这为何很有用呢?我们来看两个场景。下面是第一个场景:

>>> x = {}
>>> y = x
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x = {}
>>> x = {}
>>> y
{'key': 'value'}

下面是第二个场景:

>>> x = {}
>>> y = x
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x.clear()
>>> y
{}

在这两个场景中, x 和 y 最初都指向同一个字典。在第一个场景中,我通过将一个空字典赋 给 x 来“清空”它。这对 y 没有任何影响,它依然指向原来的字典。这种行为可能正是你想要的,但要删除原来字典的所有元素,必须使用 clear 。如果这样做, y 也将是空的,如第二个场景所示。

copy

方法 copy 返回一个新字典,其包含的键-值对与原来的字典相同(这个方法执行的是浅复制, 因为值本身是原件,而非副本)。

>>> x = {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
>>> y = x.copy()
>>> y['username'] = 'mlh'
>>> y['machines'].remove('bar')
>>> y
{'username': 'mlh', 'machines': ['foo', 'baz']}
>>> x
{'username': 'admin', 'machines': ['foo', 'baz']}

如你所见,当替换副本中的值时,原件不受影响。然而,如果修改副本中的值(就地修改而不是替换),原件也将发生变化,因为原件指向的也是被修改的值(如这个示例中的 ’machines’列表所示)。 为避免这种问题,一种办法是执行深复制,即同时复制值及其包含的所有值,等等。为此, 可使用模块 copy 中的函数 deepcopy 。

>>> from copy import deepcopy
>>> d = {}
>>> d['names'] = ['Alfred', 'Bertrand']
>>> c = d.copy()
>>> dc = deepcopy(d)
>>> d['names'].append('Clive')
>>> c
{'names': ['Alfred', 'Bertrand', 'Clive']}
>>> dc
{'names': ['Alfred', 'Bertrand']}

fromkeys

方法 fromkeys 创建一个新字典,其中包含指定的键,且每个键对应的值都是 None 。

>>> {}.fromkeys(['name', 'age'])
{'name': None, 'age': None}

这个示例首先创建了一个空字典,再对其调用方法 fromkeys 来创建另一个字典,这显得有点多余。你可以不这样做,而是直接对 dict (前面说过, dict 是所有字典所属的类型。类和类型将在第7章详细讨论)调用方法 fromkeys 。

>>> dict.fromkeys(['name', 'age'])
{'name': None, 'age': None}

如果你不想使用默认值 None ,可提供特定的值。

>>> dict.fromkeys(['name', 'age'], '(unknown)')
{'name': '(unknown)', 'age': '(unknown)'}

pop

方法 pop 可用于获取与指定键相关联的值,并将该键-值对从字典中删除。

>>> d = {'x': 1, 'y': 2}
>>> d.pop('x')
1
>>> d
{'y': 2}

popitem

方法 popitem 类似于 list.pop ,但 list.pop 弹出列表中的最后一个元素,而 popitem 随机地弹出一个字典项,因为字典项的顺序是不确定的,没有“最后一个元素”的概念。如果你要以高效地方式逐个删除并处理所有字典项,这可能很有用,因为这样无需先获取键列表。

>>> d = {'url': 'http://www.python.org', 'spam': 0, 'title': 'Python Web Site'}
>>> d.popitem()
('title', 'Python Web Site')
>>> d
{'url': 'http://www.python.org', 'spam': 0}

虽然 popitem 类似于列表方法 pop ,但字典没有与 append (它在列表末尾添加一个元素)对应的方法。这是因为字典是无序的,类似的方法毫无意义。

update

方法 update 使用一个字典中的项来更新另一个字典。

>>> d ={
>>>     'title': 'Python Web Site',
>>>     'url': 'http://www.python.org',
>>>     'changed': 'Mar 14 22:09:15 MET 2016'
>>>     }
>>>
>>> x = {'title': 'Python Language Website'}
>>> d.update(x)
>>> d
{'title': 'Python Language Website',
 'url': 'http://www.python.org',
 'changed': 'Mar 14 22:09:15 MET 2016'}

对于通过参数提供的字典,将其项添加到当前字典中。如果当前字典包含键相同的项,就替换它。可像调用本章前面讨论的函数 dict (类型构造函数)那样调用方法 update 。这意味着调用update 时,可向它提供一个映射、一个由键-值对组成的序列(或其他可迭代对象)或关键字参数。