字典

[!NOTE]

以下内容部分摘录自《Python编程快速上手——让繁琐的工作自动化(第二版)》,并加入了一些自己的理解,仅用于个人交流与学习,如涉及侵权请联系站长删除!

1. 字典数据类型

​ 像列表一样,字典是许多值的集合,但不像列表的索引,字典的索引可以使用许多不同的数据类型,不只是整数。

  • 字典的索引:字典的索引被称之为“键”,键及其关联的值被称之为“键-值对”。
  • 注意:字典输入时带{}

​ 接下来我们可以试着创建一个字典并赋给变量myCat

1
2
3
4
myCat = {'size': 'fat', 'color':'gray', 'disposition':'loud'}
print(myCat['size']) # 输出的结果是fat
print('My cat has ' + myCat['color'] + ' fur') # 输出的结果是My cat has gray fur
print()
  • 解释:变量myCat中的这个字典的键就是sizecolordisposition,而他们相对应的值对就是fatgrayloud。而我们print所打印的值就是这些值。

​ 就像列表一样字典也可以用整数作为键,但他可以是任何数字,不必用零开始,如下所示:

1
2
spam = {12345: 'Luggage Combination', 42: 'The Answer'}
print(spam[12345], spam[42]) # 输出的结果为Luggage Combination The Answer

1.1 字典与列表

不像列表,字典中的项目是不排序的。

1
2
3
4
5
6
7
spam = ['cat', 'dogs', 'moose']
bacon = ['dogs', 'moose', 'cats']
print(spam == bacon) # 输出的结果为False

eggs = {'name': 'Zophie', 'species': 'cats', 'age': '8'}
ham = {'species': 'cats', 'age': '8', 'name': 'Zophie'}
print(eggs == ham) # 输出的结果为True
  • 解释:在名为spam的列表中,第一项是spam[0],但在字典中没有“第一个”项,虽然在确定两个列表是否相同的,表象的顺序很重要,但在字典中“键-值对”输入的顺序并不重要。(因为字典是不排序的,所以不能像列表那样切片)。

尝试访问列表中不存在的键,将会出现KeyError报错信息

1
2
spam = {'name': 'Zophie', 'age': 7}
print(spam['color'])
  • 解释:输入以上代码并试着运行起来就会发现KeyError错误信息。

我们可以通过字典是不排序的,可以使用任意的值来作为键来编写一个小程序,用来记录朋友的生日

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
birthdays = {'Alice': 'Apr 1', 'Bob': 'Dec 12', 'Carol': 'Mar 4'}

while True:
print('Enter a name : (blank to quit)')
name = input()
if name == ' ':
break

if name in birthdays:
print(birthdays[name] + ' is the birthday of ' + name)
else:
print('I do not have birthday information for ' + name)
print('What is their birthday?')
bday = input()
birthdays[name] = bday #将字典中没有的项 添加进字典中
print('Birthday database updated')
print(birthdays)
  • 解释:这里创建了一个字典将他保存到名叫birthday的变量中,用来存放生日。用in关键字,可以查看输入的名字是否作为键存放在字典中。如果在字典中,我们可以用[]访问他们关联的值,如果不在我们可以用同样的方法添加他们。(程序终止时输入的所有数据就丢失了,因为我们没有将他们保存在硬盘文件中。)

1.2 keys()values()item()方法

​ 字典中有三个方法,他们将返回类似列表的值,分别对应字典的键、值、键-值对:keys()values()item()方法。这些方法返回的值不是真正的列表,他们不可被修改,没有append()方法,但这些数据类型 可以使用for循环。

1
2
3
4
5
6
7
8
9
spam = {'color': 'red', 'age': 42}
for v in spam.values():
print(v) # 输出的结果为red和42

for k in spam.keys():
print(k) # 输出的结果为color和age

for i in spam.items():
print(i) # 输出的结果为('color', 'red')和('age', 42)
  • 解释:利用keys()values()item()方法,循环分别可以迭代键、值、键-值对。需要注意的是,item()方法返回的dict_item值包含的是键和值的元组,如果希望的到一个真正的列表,就把类似列表的值返回给list()函数,具体如下:

    1
    2
    3
    spam2 = {'color': 'red', 'age': 42}
    print(spam2.keys()) # 输出的结果为dict_keys(['color', 'age'])
    print(list(spam2.keys())) # 输出的结果为['color', 'age']
    • 解释list(sapm2.keys())代码接收keys()函数返回的dict_keys值,并传给list()函数,然后返回一个列表,即['color', 'age']

​ 也可以利用多重赋值技巧,在for循环中将键和值赋给不同的变量。

1
2
3
spam3 = {'color': 'red', 'age': 42}
for k, v in spam3.items():
print('Key: ' + k + ' Value: ' + str(v)) # 输出的结果为Key: color Value: red和Key: age Value: 42

1.3 检查字典中是否存在键或值

in或者in not操作符可以检查值是否存在于列表中,也可以利用这些操作符检查某个键或值是否存在于字典中。

1
2
3
4
5
6
spam = {'name': 'Zophie', 'age': 7}
print('name' in spam.keys()) # 输出的结果为True
print('Zophie' in spam.values()) # 输出的结果为True
print('color' in spam.keys()) # 输出的结果为False
print('color' not in spam.keys()) # 输出的结果为True
print('color' in spam) # 输出的结果为False
  • 解释:请注意 在前面的例子中‘color' in spam本质上是一个简写的版本 相当于'color' in spam.keys(),这种情况总是对的 如果要想检查一个值是否为字典中的键 就可以将关键字in或者not in作用于该字典本身。

1.4 get()方法

​ 在访问一个值之前,检查该键是否在字典中,这很麻烦。这里我们用到get()方法,他有两个参数:1.要取得其值的键 2.当该键不存在时,返回备用的值。

1
2
3
picnicItems = {'apple': 5, 'cups': 2}
print('I am bringing ' + str(picnicItems.get('cups', 0)) + ' cups.') # 输出的结果是I am bringing 2 cups
print('I am bringing ' + str(picnicItems.get('eggs', 0)) + ' eggs.') # 输出的结果是I am bringing 0 eggs
  • 解释:因为picnicItems字典中没有'eggs'键 所以get()方法返回的默认值是0,不使用get()方法就会报错。

1.5 setdefault()方法

​ 我们常常需要为字典中的某一个键设置一个默认值,当该键没有任何值使用它时。代码看起来像这样:

1
2
3
4
spam = {'name': 'Pooka', 'age': 5}
if 'color' not in spam:
spam['color'] = 'black'
print(spam)

setdefualt()方法提供了一种方式,可以在一行中完成这件事,该方法有两个参数:1.第一个参数是要检查的键(即查看该键是否在字典中)2.第二个参数是当该键不存在时需要设置的值。注意:如果该键的确存在,setdefualt()方法就会返回键的值,如果不存在则会返回setdefualt()方法的第二个参数值。

1
2
3
4
5
6
spam = {'name': 'Pooka', 'age': 5}
print(spam.setdefault('color', 'black')) # 输出的结果为black
print(spam) # 输出的结果为{'name': 'Pooka', 'age': 5, 'color': 'black'}

print(spam.setdefault('color', 'white')) # 输出的结果为black
print(spam) # 输出的结果为{'name': 'Pooka', 'age': 5, 'color': 'black'}
  • 解释:当第一次调用setdefualt()方法时,spam变量中的字典变为{'color': 'black', 'age': 5, 'name': 'Pooka'},该方法的返回值为black
  • 解释:当第二次调用setdefualt()方法时,我们可以发现输出的结果没有变化,这是因为spam变量中的字典里已经有了名为'color'的键了。

setdefualt()方法是一个很好的快捷方式,可以确保有一个键的存在,下面这个程序可以计算一个字符串中每个字符出现的次数。

1
2
3
4
5
6
message = 'It was a bright cold day in April, and the clocks were striking thirteen.' 
count = {}
for character in message:
count.setdefault(character, 0)
count[character] = count[character] + 1
print(count)
  • 解释message存放我们需要计算的字符串,count = {}这里我们初始化了一个空字典,用来存放字符及其出现次数,for character in message:这里我们遍历字符串(包括空格和标点符号),一次将字符赋值给变量charactercount.setdefault(character, 0)这里我们调用setdefualt()方法:若 character 不在字典中,则添加该键并设置默认值 0,若已存在,则不改变其当前值。最后我们在使用count[character] = count[character] + 1将当前字符的计数值加1,更新到字典中。

2. 美观的输出

​ 如果程序中导入了pprint()模块,就可以使用pprint()pformat()函数,这些函数将为我们美观的输出一个字典,以我们上方的字符串计算程序为例:

1
2
3
4
5
6
7
8
9
import pprint
message = 'It was a bright cold day in April, and the clocks were striking thirteen.'
count = {}
for character in message:
count.setdefault(character, 0)
count[character] = count[character] + 1
pprint.pprint(count)

print(pprint.pformat(count))

​ 以上代码的输出结果如下(pprint.pprint()print(pprint.pformat())是等价的,所以我们只展示一遍。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{' ': 13,
',': 1,
'.': 1,
'A': 1,
'I': 1,
'a': 4,
'b': 1,
'c': 3,
'd': 3,
'e': 5,
'g': 2,
'h': 3,
'i': 6,
'k': 2,
'l': 3,
'n': 4,
'o': 2,
'p': 1,
'r': 5,
's': 3,
't': 6,
'w': 2,
'y': 1}