blog
blog copied to clipboard
Python之旅:第四章-当索引行不通时:使用字典
Table of Contents generated with DocToc
-
Python之旅:第四章 当索引行不通时:使用字典
- 字典的用途
-
创建和使用字典
- 函数dict
- 基本的字典操作
- 将字符串格式设置功能用于字典
-
字典方法
- clear
- copy
- fromkeys
- get
- itmes
- keys
- pop
- popitem
- setdefault
- update
- values
Python之旅:第四章 当索引行不通时:使用字典
前面几个章节介绍的序列是一种通过索引(编号)来访问各个元素的数据结构。通过名称来访问其各个元素值的数据结构,叫做映射(mapping),而字典则是Python中唯一的内置映射类型。字典中的值是没有顺序的,而是存储在键下,键可以是数字、字符串或元组。
字典的用途
字典的名称指出了这种数据结构的用途。字典旨在让你能轻松的找到特定的单词(键),以获得其定义的(值)
例如:如果我们要创建一个人的序列,但需要根据人来找到其电话号码,则必须创建两个list,然后一一对应的找到其值,使用列表是可行的,但使用字典是最佳方式,且效率更高。
创建和使用字典
创建字典类似下面的这种表示方式:
phonebook = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
字典由键及其相应的值组成,这种键-值对称为项(item),每个键与其值之间都用冒号(:
)分隔,项之间用逗号分隔,而整个字典放在花括号内。空字典直接使用两个花括号表示:{}
。特别注意:在字典中的键必须是唯一的,而值则无需如此。
函数dict
可使用函数dict
从其他映射(如其他字典)或键-值对序列创建字典
>>> items = [('name', 'Gumby'), ('age', 42)]
>>> d = dict(items)
>>> d
{'name': 'Gumby', 'age': 42}
还可以使用关键字实参来调用这个函数:
>>> d = dict(name='Gumby', age=42)
>>> d
{'name': 'Gumby', 'age': 42}
就像函数list
、tuple
和str
一样,如果调用dict
函数时没有提供任何实参,将返回一个空字典。
基本的字典操作
字典的基本行为在很多方面都类似于序列
-
len(d)
: 返回字典d
包含的项(键值对)的数量 -
d[k]
: 返回与键k
相关联的值。 -
d[k] = v
: 将值v
关联到键k
-
del d[k]
: 删除键为k
的项 -
k in d
: 检查字典d是否包含键为k的项
字典与序列的不同之处:
- 键的类型:序列中只有索引,类似于字典中的键,但它只能为整数,而字典中的键可以是整数,也可以是任何不可变的类型,比如浮点数、字符串或元组
- 自动添加:即便是字典中原本没有的键,也可以给它赋值,这将在字典中创建一个新项,然后,我们不能给列表中没有的元素赋值
- 成员资格:在字典中,表达式
k in d
(d
是一个字典),查找的是键,而不是值,在序列中,表达式v in l
(l
是一个列表),查找的是值而不是索引。
字典中的键可以是任何不可变的类型,这一点是字典的主要优点,看下面的示例:
>>> x = []
>>> x[42] = 'Foobar'
Traceback (most recent call last):
File "<pyshell#130>", line 1, in <module>
x[42] = 'Foobar'
IndexError: list assignment index out of range
>>> x = {}
>>> x[42] = 'Foobar'
>>> x
{42: 'Foobar'}
如果要给空的列表添加新的项,上面的操作是不可行的,然而,字典却可以。
看下面的例子:
# 一个简单的数据库
# 一个将人名用作键的字典,每个人都用一个字典表示
# 字典包含键'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: Alice
Phone number (p) or address (a)? p
Alice's phone number is 2341.
将字符串格式设置功能用于字典
通过字典,我们可以使用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>
字典方法
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和y都指向同一个字典对象
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x = {} # 当给x赋值空字典后,y依然指向原来的对象
>>> y
{'key': 'value'}
>>> x = {}
>>> y = x # x和y都指向同一个字典对象
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x.clear() # 当使用clear清空x后,y的指向也被删除了
>>> 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']}
还有一种复制,叫深复制,即同时复制值及其包含的所有值,执行深复制可使用模块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}
上面的行为有点多余,你可以直接使用dict
来调用fromkeys
方法:
>>> dict.fromkeys(['name', 'age'])
{'name': None, 'age': None}
如果你不想使用默认值None
,可以提供特定的值
>>> dict.fromkeys(['name', 'age'], '(unknown)')
{'name': '(unknown)', 'age': '(unknown)'}
get
方法get
为访问字典项提供了宽松的环境,通常情况下,如果我们访问字典中没有的项,会引发错误:
>>> d = {}
>>> print(d['name'])
Traceback (most recent call last):
File "<pyshell#192>", line 1, in <module>
print(d['name'])
KeyError: 'name'
而使用get
则不会:
>>> d = {}
>>> print(d.get('name'))
None
当使用get
来访问字典中不存在的键时,没有引发异常,而是返回了None
,我们还可以指定默认值:
>>> d.get('name', 'N/A')
'N/A'
如果字典中包含指定的值,则它与普通的字典查找相同。
下面是一个使用get
查找简单数据库的示例:
# 一个使用get()的简单数据库
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)? ')
# 使用正确的键
key = request # 如果request既不是'p'也不是'a'
if request == 'p': key = 'phone'
if request == 'a': key = 'addr'
# 使用get提供默认值
person = people.get(name, {})
label = labels.get(key, key)
result = person.get(key, 'not available')
print("{}'s {} is {}.".format(name, label, result))
运行结果如下:
Name: Beth
Phone number(p) or address (a)? p
Beth's phone number is 9102.
itmes
方法items
返回一个包含所有字典项的列表,其中每个元素都为(key, value)
的形式,字典项咋系列表中的排列顺序不确定。
>>> d = {'title': 'Python Web Site', 'url': 'https://www.python.org', 'spam': 0}
>>> d.items()
dict_items([('title', 'Python Web Site'), ('url', 'https://www.python.org'), ('spam', 0)])
返回值是一种名为字典视图的特殊类型,字典视图可用于迭代,我们还可以获取其长度以及执行成员资格检查
>>> it = d.items()
>>> len(it)
3
>>> ('spam', 0) in it
True
字典视图的优点就是不复制,它们始终是底层字典的反映,即便是修改了底层字典也是如此:
>>> d['spam'] = 1
>>> ('spam', 0) in it
False
>>> d['spam'] = 0
>>> ('spam', 0) in it
True
我们也可以手动复制字典项到列表中
>>> list(d.items())
[('title', 'Python Web Site'), ('url', 'https://www.python.org'), ('spam', 0)]
keys
方法keys
返回一个字典视图,其中包含指定字典中的键
pop
方法pop
可用于获取与指定键相关联的值,并将该键值对从字典中删除
>>> d = {'x': 1, 'y': 2}
>>> d.pop('x')
1
>>> d
{'y': 2}
popitem
方法popitem
随机的弹出一个字典项,因为字典项的顺序是不确定的,没有'最后一个元素'的概念。
>>> d = {'title': 'Python Web Site', 'url': 'https://www.python.org', 'spam': 0}
>>> d.popitem()
('spam', 0)
>>> d
{'title': 'Python Web Site', 'url': 'https://www.python.org'}
setdefault
方法setdefault
有点像get
,因为它也获取与指定键相关联的值,但除此之外,它还在字典不包含指定的键时,在字典中添加指定的键值对
>>> d = {}
>>> d.setdefault('name', 'N/A')
'N/A'
>>> d
{'name': 'N/A'}
>>> d['name'] = 'Gumby'
>>> d.setdefault('name', 'N/A')
'Gumby'
>>> d
{'name': 'Gumby'}
update
方法update
使用一个字典的项来更新另一个字典
>>> d = {
'title': 'Python Web Site',
'url': 'https://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': 'https://www.python.org', 'changed': 'Mar 14 22:09:15 MET 2016'}
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])
本章节完毕
本系列目录: