目录
通过名称来访问其各个值的数据结构。这种数据结构称为映射 (mapping)。字典是Python中唯一的内置映射类型,其中的值不按顺序排列,而是存储在键下。键可能是数、字符串或元组。
1. 创建和使用字典
字典由键及其相应的值组成,这种键-值对称为项 (item)。
每个键与其值之间都用冒号(: )分隔,项之间用逗号分隔,而整个字典放在花括号内。空字典(没有任何项)用两个花括号表示,类似于下面这样:{} 。
在字典(以及其他映射类型)中,键必须是独一无二的,而字典中的值无需如此。
1.1 函数dict
可使用函数dict从其他映射(如其他字典)或键-值对序列创建字典。
与list 、tuple 和str 一样,dict 其实根本就不是函数,而是一个类。
>>> items = [('name', 'Gumby'), ('age', 42)]
>>> d = dict(items)
>>> d
{'age': 42, 'name': 'Gumby'}
>>> d['name']
'Gumby'
可使用关键字实参 来调用这个函数
>>> d = dict(name='Gumby', age=42)
>>> d
{'age': 42, 'name': 'Gumby'}
1.2 字典的基本操作
字典的基本行为在很多方面都类似于序列。
- len(d) 返回字典d 包含的项(键-值对)数。
- d[k] 返回与键k 相关联的值。
- d[k] = v 将值v 关联到键k 。
- del d[k] 删除键为k 的项。
- k in d 检查字典d 是否包含键为k 的项。
字典和列表不同之处:
- 键的类型 :字典中的键可以是整数,但并非必须是整数。字典中的键可以是任何不可变的类型,如浮点数(实数)、字符串或元组。
- 自动添加 :即便是字典中原本没有的键,也可以给它赋值,这将在字典中创建一个新项。然而,如果不使用append 或其他类似的方法,就不能给列表中没有的元素赋值。
- 成员资格 :表达式k in d (其中d 是一个字典)查找的是键而不是值,而表达式v in l (其中l 是一个列表)查找的是值而不是索引。这看似不太一致,但你习惯后就会觉得相当自然。毕竟如果字典包含指定的键,检查相应的值就很容易。
相比于检查列表是否包含指定的值,检查字典是否包含指定的键的效率更高。数据结构越大,效率差距就越大。
将字符串'Foobar' 赋给一个空列表中索引为42的元素。这显然不可能,因为没有这样的元素。要让这种操作可行,初始化x 时,必须使用[None] * 43 之类的代码,而不能使用[]
>>> x = []
>>> x[42] = 'Foobar'
# Traceback (most recent call last):
# File "<stdin>", line 1, in ?
# IndexError: list assignment index out of range
>>> x = {}
>>> x[42] = 'Foobar'
>>> x
{42: 'Foobar'}
1.3 将字符串格式设置功能用于字典
可以用format_map提取字典中已经存在的信息。
>>> phonebook
{'Beth': '9102', 'Alice': '2341', 'Cecil': '3258'}
>>> "Cecil's phone number is {Cecil}.".format_map(phonebook)
"Cecil's phone number is 3258."
>>> 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>
1.4 字典方法
01. clear
方法clear 删除所有的字典项,这种操作是就地执行的(就像list.sort 一样),因此什么都不返回(或者说返回None )。
>>> d = {}
>>> d['name'] = 'Gumby'
>>> d['age'] = 42
>>> d
{'age': 42, 'name': 'Gumby'}
>>> returned_value = d.clear()
>>> d
{}
>>> print(returned_value)
None
02. 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']}
当替换副本中的值时,原件不受影响。然而,如果修改 副本中的值(就地修改而不是替换),原件也将发生变化,因为原件指向的也是被修改的值。
为避免这种问题,一种办法是执行深复制 ,即同时复制值及其包含的所有值,等等。为此,可使用模块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']}
03. fromkeys
方法fromkeys 创建一个新字典,其中包含指定的键,且每个键对应的值都是None 。
>>> {}.fromkeys(['name', 'age'])
{'age': None, 'name': None}
>>> dict.fromkeys(['name', 'age'])
{'age': None, 'name': None}
# 可修改默认值None
>>> dict.fromkeys(['name', 'age'], '(unknown)')
{'age': '(unknown)', 'name': '(unknown)'}
04. get
方法get 为访问字典项提供了宽松的环境。通常,如果你试图访问字典中没有的项,将引发错误。
>>> d = {}
>>> print(d['name'])
# Traceback (most recent call last):
# File "<stdin>", line 1, in ?
# KeyError: 'name'
使用get不会这样。使用get 来访问不存在的键时,没有引发异常,而是返回None 。可指定“默认”值,这样将返回指定的值而不是None 。
>>> print(d.get('name'))
None
>>> d.get('name', 'N/A')
'N/A'
如果字典包含指定的键,get 的作用将与普通字典查找相同。
>>> d['name'] = 'Eric'
>>> d.get('name')
'Eric'
05. items
方法items 返回一个包含所有字典项的列表,其中每个元素都为(key, value) 的形式。字典项在列表中的排列顺序不确定。
>>> d = {'title': 'Python Web Site', 'url': 'http://www.python.org', 'spam': 0}
>>> d.items()
dict_items([('url', 'http://www.python.org'), ('spam', 0), ('title', 'Python Web Site')])
获取长度和资格检查
>>> it = d.items()
>>> len(it)
3
>>> ('spam', 0) in it
True
06. keys
方法keys 返回一个字典视图,其中包含指定字典中的键。
07. pop
方法pop 可用于获取与指定键相关联的值,并将该键-值对从字典中删除。
>>> d = {'x': 1, 'y': 2}
>>> d.pop('x')
1
>>> d
{'y': 2}
08. popitem
方法popitem 类似于list.pop ,但list.pop 弹出列表中的最后一个元素,而popitem 随机地弹出一个字典项,因为字典项的顺序是不确定的,没有“最后一个元素”的概念。
>>> d = {'url': 'http://www.python.org', 'spam': 0, 'title': 'Python Web Site'}
>>> d.popitem()
('url', 'http://www.python.org')
>>> d
{'spam': 0, 'title': 'Python Web Site'}
虽然popitem 类似于列表方法pop ,但字典没有与append (它在列表末尾添加一个元素)对应的方法。这是因为字典是无序的。
09. setdefault
方法setdefault 有点像get ,因为它也获取与指定键相关联的值,但除此之外,setdefault 还在字典不包含指定的键时,在字典中添加指定的键-值对。
>>> d = {}
>>> d.setdefault('name', 'N/A')
'N/A'
>>> d
{'name': 'N/A'}
>>> d['name'] = 'Gumby'
>>> d.setdefault('name', 'N/A')
'Gumby'
>>> d
{'name': 'Gumby'}
指定的键不存在时,setdefault 返回指定的值并相应地更新字典。如果指定的键存在,就返回其值,并保持字典不变。与get 一样,值是可选的;如果没有指定,默认为None 。
>>> d = {}
>>> print(d.setdefault('name'))
None
10. 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
{'url': 'http://www.python.org', 'changed':
'Mar 14 22:09:15 MET 2016', 'title': 'Python Language Website'}
11. values
法values 返回一个由字典中的值组成的字典视图。不同于方法keys ,方法values 返回的视图可能包含重复的值。
>>> d = {}
>>> d[1] = 1
>>> d[2] = 2
>>> d[3] = 3
>>> d[4] = 1
>>> d.values()
dict_values([1, 2, 3, 1])