Dictionary Uses
名称字典应该会给你关于这个结构的用途的线索。一本普通的书是为从头到尾阅读而制作的。如果您愿意,您可以快速打开它到任何给定的页面。这有点像Python列表。另一方面,实际字典和Python等价词典的构造都是为了便于查找特定单词(键)以找到其定义(值)。
在许多情况下,字典比列表更合适。这里有一些用法的例子Python字典:
- 表示游戏板的状态,每个键都是坐标的元组
- 以文件名作为键存储文件修改时间
- 数字电话/通讯录
假设你有一个人的列表。
>>> names = ['Alice', 'Beth', 'Cecil', 'Dee-Dee', 'Earl']
如果您想创建一个小数据库来存储它们的电话号码呢人们,你会怎么做?一种方法是再列一个清单。假设你只存储它们四位数的扩展。然后你会得到这样的结果:
>>> numbers = ['2341', '9102', '3158', '0142', '5551']
一旦你创建了这些列表,你可以查找塞西尔的电话号码如下:
>>> numbers[names.index('Cecil')]
'3158
这是可行的,但有点不切实际。你真正想要做的是如下的事情:
>>> phonebook['Cecil']
'3158
你猜怎么着?如果电话簿是一本字典,你就可以这样做。
Creating and Using Dictionaries
字典是这样写的:
phonebook = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
字典由键及其对应的值对(称为项)组成。在本例中,是名称是键,而电话号码是值。每个键与其值之间用冒号(:)分隔,项目用逗号分隔,整个部分用大括号括起来。一个空的字典(没有任何项)是用两个花括号编写的,像这样:{}。
The dict Function
可以使用dict function1从其他映射(例如,other)构造字典字典)或(键、值)对序列。
>>> 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'}
尽管这可能是dict最有用的应用程序,但也可以将它与映射参数一起使用,以创建具有与映射相同项字典。(如果使用不带任何参数,它会返回一个新的空字典,就像其他类似的功能,比如列表、元组,和str)如果其他映射字典(毕竟,这是唯一内置映射类型),你可以使用字典方法复制相反,如在本章后面所述。
Basic Dictionary Operations
字典的基本行为在很多方面反映了序列的基本行为。
- len(d)返回d中的项数(键值对)。
- d[k]返回与键k相关联的值。
- d[k] = v将值v与键k关联起来
- 删除键为k的项。
- d中的k检查d中是否有一个项的键值为k。
第一点——键可以是任何不可变类型——是字典的主要优势。第二点也很重要。看看这里的区别:
>>> 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'}
首先,我尝试分配字符串'Foobar'位置42在一个空列表显然不可能,因为该位置不存在。为了使这成为可能,我必须用[None] * 43或其他东西来初始化x,而不是简单地用[]。然而,下一次尝试非常成功。这里我将'Foobar'赋值给一个空字典的键42。您可以看到这里没有问题。一个新条目被简单地添加到字典中,我就开始工作了。
Listing 4-1. Dictionary Example
# A simple database
# A dictionary with person names as keys. Each person is represented as
# another dictionary with the keys 'phone' and 'addr' referring to their phone
# number and address, respectively.
people = {
'Alice': {
'phone': '2341',
'addr': 'Foo drive 23'
},
'Beth': {
'phone': '9102',
'addr': 'Bar street 42'
},
'Cecil': {
'phone': '3158',
'addr': 'Baz avenue 90'
}
}
# Descriptive labels for the phone number and address. These will be used
# when printing the output.
labels = {
'phone': 'phone number',
'addr': 'address'
}
name = input('Name: ')
# Are we looking for a phone number or an address?
request = input('Phone number (p) or address (a)? ')
# Use the correct key:
if request == 'p': key = 'phone'
if request == 'a': key = 'addr'
# Only try to print information if the name is a valid key in
# our dictionary:
if name in people: print("{}'s {} is {}.".format(name, labels[key], people[name][key]))
运行结果:
String Formatting with Dictionaries
在第3章中,您看到了如何使用字符串格式来格式化作为format方法的单个(命名或未命名)参数提供的值。有时,以字典的形式收集一组命名值会使事情变得更简单。例如,字典可能包含所有类型的信息,而您的格式字符串将只挑选出它需要的任何信息。您必须通过使用format_map指定要提供一个映射。
>>> phonebook
{'Beth': '9102', 'Alice': '2341', 'Cecil': '3258'}
>>> "Cecil's phone number is {Cecil}.".format_map(phonebook)
"Cecil's phone number is 325
在使用这样的字典时,您可以使用任意数量的转换说明符,只要给定的所有键可以在字典中找到。这种字符串格式在模板系统中非常有用例中使用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>
Dictionary Methods
与其他内置类型一样,字典也有方法。虽然这些方法可能非常有用,但您需要可能不像列表和字符串方法那样经常需要它们。你可能想要先浏览这一部分先了解哪些方法是可用的,然后如果需要确切地了解如何使用给定的方法。
clear
clear方法从字典中删除所有项。这是一个就地操作(如list.sort),所以它不返回任何东西(或者更确切地说,没有)。
>>> d = {}
>>> d['name'] = 'Gumby'
>>> d['age'] = 42
>>> d
{'age': 42, 'name': 'Gumby'}
>>> returned_value = d.clear()
>>> d
{}
>>> print(returned_value)
None
为什么这个有用?让我们考虑两种情况。这是第一个:
>>> x = {}
>>> y = x
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x = {}
>>> x = {}
{'key': 'value'}
这是第二种情况:
>>> x = {}
>>> y = x
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x.clear()
>>> y
{}
在这两种情况下,x和y最初指的是同一个字典。在第一个场景中,我通过给x分配一个新的空字典来空白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'列表)。避免这个问题的一种方法是进行深度复制,复制值及其包含的任何值,等等。您可以使用复制模块中的函数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方法使用给定的键创建一个新的字典,每个键都有一个默认的对应值
>>> {}.fromkeys(['name', 'age'])
{'age': None, 'name': None}
本例首先构造一个空字典,然后调用该空字典上的fromkeys方法,以创建另一个字典(这是一个有点冗余的策略)。相反,您可以直接在dict上调用该方法,dict(如前所述)是所有字典的类型。(类型和类的概念将在第7章中更深入地讨论。)
>>> dict.fromkeys(['name', 'age'])
{'age': None, 'name': None}
如果不想使用None作为默认值,可以提供自己的默认值。
>>> dict.fromkeys(['name', 'age'], '(unknown)')
{'age': '(unknown)', 'name': '(unknown)'
get
get方法是访问字典项的一种宽容的方式。通常,当您试图访问字典中不存在的项时,情况会非常糟糕。
>>> d = {}
>>> print(d['name'])
Traceback (most recent call last):
File "<stdin>", line 1, in ?
KeyError: 'name
get不是这样的。
>>> print(d.get('name'))
None
如您所见,当您使用get访问一个不存在的密钥时,不会出现异常。相反,您得到的值是None。您可以提供自己的默认值,然后使用该值而不是None。
>>> d.get('name', 'N/A')
'N/A
如果键存在,get就像普通的字典查找一样工作。
>>> d['name'] = 'Eric'
>>> d.get('name')
'Eric
Listing 4-2显示了清单4-1中程序的修改版本,它使用get方法访问数据库条目。
# A simple database using get()
# Insert database (people) from Listing 4-1 here.
labels = {
'phone': 'phone number',
'addr': 'address'
}
name = input('Name: ')
# Are we looking for a phone number or an address?
request = input('Phone number (p) or address (a)? ')
# Use the correct key:
key = request # In case the request is neither 'p' nor 'a'
if request == 'p': key = 'phone'
if request == 'a': key = 'addr'
# Use get to provide default values:
person = people.get(name, {})
label = labels.get(key, key)
result = person.get(key, 'not available')
print("{}'s {} is {}.".format(name, label, result))
下面是该程序的运行示例。注意,即使用户输入的值是我们没有准备好的,get增加的灵活性也允许程序给出有用的响应
items
items方法以项目列表的形式返回字典中的所有项目,其中每个项目的形式(键、值)。这些items不会以任何特定的顺序返回。
>>> 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')])
返回值是一种特殊类型,称为字典视图。字典视图可以用于迭代(更多信息请参见第5章)。此外,您还可以确定其长度并检查其成员资格。
>>> 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
但是,如果您希望将这些项复制到列表中(在较旧版本的Python中使用项时就会发生这种情况),那么您总是可以自己完成这项工作。
>>> list(d.items())
[('spam', 0), ('title', 'Python Web Site'), ('url', 'http://www.python.org')]
keys
keys方法返回字典中键的字典视图。
pop
pop方法可用于获得与给定键值对应的值,然后删除键值字典里的一对。
>>> d = {'x': 1, 'y': 2}
>>> d.pop('x')
1
>>> d
{'y': 2}
popitem
popitem方法类似于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(将元素添加到列表末尾)等价的字典。因为字典没有顺序,所以这样的方法没有任何意义。
setdefault
setdefault方法与get有点类似,因为它检索与给定键相关联的值。除了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一样;如果它被省略,则不使用。
>>> d = {}
>>> print(d.setdefault('name'))
None
>>> d
{'name': None}
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'}
将提供的字典中的项添加到旧字典中,用相同的键替换其中的任何项。可以使用与dict函数(或类型构造函数)相同的方式调用update方法,正如本章前面讨论的那样。这意味着可以使用(键、值)对或关键字参数的映射、序列(或其他可迭代对象)来调用update。
values
values方法返回字典中值的字典视图。与键不同,值返回的视图可能包含重复的值。
>>> d = {}
>>> d[1] = 1
>>> d[2] = 2
>>> d[3] = 3
>>> d[4] = 1
>>> d.values()
dict_values([1, 2, 3, 1])
参考:Beginning Python From Novice to Professional, 3rd Edition 第四章