第5章 字典和结构化数据
5.1 字典数据类型
像列表一样,“字典”是许多值的集合。但不像列表的下标,字典的索引可以使用许多不同数据类型,不只是整数。字典的索引被称为“键”,键及其关联的值称为“键-值”对。在代码中,字典输入时带花括号{}。
>>> myCat = {'size': 'fat', 'color': 'gray', 'disposition': 'loud'}
这将一个字典赋给myCat变量。这个字典的键是'size'、'color'和'disposition'。这些键相应的值是'fat'、'gray'和'loud'。可以通过它们的键访问这些值。
>>> myCat['size']
'fat'
>>> 'My cat has ' + myCat['color'] + ' fur.'
'My cat has gray fur.'
字典仍然可以用整数值作为键,就像列表使用整数值作为下标一样,但它们不必从0开始,可以是任何数字。
>>> spam = {12345: 'Luggage Combination', 42: 'The Answer'}
5.1.1 字典与列表
- 虽然确定两个列表是否相同时,表项的顺序很重要,但在字典中,键-值对输入的顺序并不重要。
- 因为字典是不排序的,所以不能像列表那样切片。
- 尽管字典是不排序的,但可以用任意值作为键,这一点让你能够用强大的方式来组织数据。
❶ 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.')
你创建了一个初始的字典,将它保存在birthdays中❶。用in关键字,可以看看输入的名字是否作为键存在于字典中❷,就像查看列表一样。如果该名字在字典中,你可以用方括号访问关联的值❸。如果不在,你可以用同样的方括号语法和赋值操作符添加它❹。
5.1.2 keys()、values()和items()方法
有3个字典方法,它们将返回类似列表的值,分别对应于字典的键、值和键-值对:keys()、values()和items()。
但这些数据类型(分别是dict_keys、dict_values和dict_items)可以用于for循环。
>>> spam = {'color': 'red', 'age': 42}
>>> for v in spam.values():
print(v)
red
42
请注意,items()方法返回的dict_items值中,包含的是键和值的元组。
如果希望通过这些方法得到一个真正的列表,就把类似列表的返回值传递给 list函数。
>>> spam = {'color': 'red', 'age': 42}
>>> spam.keys()
dict_keys(['color', 'age'])
>>> list(spam.keys())
['color', 'age']
>>> spam = {'color': 'red', 'age': 42}
>>> for k, v in spam.items():
print('Key: ' + k + ' Value: ' + str(v))
Key: age Value: 42
Key: color Value: red
5.1.3 检查字典中是否存在键或值
如果想要检查一个值是否为字典中的键,就可以用关键字in(或not in),作用于该字典本身。
5.1.4 get()方法
在访问一个键的值之前,检查该键是否存在于字典中,这很麻烦。好在,字典有一个get()方法,它有两个参数:要取得其值的键,以及如果该键不存在时,返回的备用值。
>>> picnicItems = {'apples': 5, 'cups': 2}
>>> 'I am bringing ' + str(picnicItems.get('cups', 0)) + ' cups.'
'I am bringing 2 cups.'
>>> 'I am bringing ' + str(picnicItems.get('eggs', 0)) + ' eggs.'
'I am bringing 0 eggs.'
5.1.5 setdefault()方法
你常常需要为字典中某个键设置一个默认值,当该键没有任何值时使用它。
spam = {'name': 'Pooka', 'age': 5}
if 'color' not in spam:
spam['color'] = 'black'
setdefault()方法提供了一种方式,在一行中完成这件事。传递给该方法的第一个参数,是要检查的键。第二个参数,是如果该键不存在时要设置的值。如果该键确实存在,方法就会返回键的值。
setdefault()方法是一个很好的快捷方式,可以确保一个键存在。
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字符串中的每个字符,计算每个字符出现的次数。setdefault()方法调用确保了键存在于count字典中(默认值是0),这样在执行count[character] = count[character] + 1时,就不会抛出KeyError错误。
5.2 漂亮打印
如果程序中导入pprint模块,就可以使用pprint()和pformat()函数,它们将“漂亮打印”一个字典的字。
pprint.pprint(someDictionaryValue)
print(pprint.pformat(someDictionaryValue))
如果字典本身包含嵌套的列表或字典,pprint.pprint()函数就特别有用。
如果希望得到漂亮打印的文本作为字符串,而不是显示在屏幕上,那就调用pprint.pformat()。下面两行代码是等价的:
5.3 使用数据结构对真实世界建模
5.3.1 井字棋盘
theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ', 'mid-L': ' ', 'mid-M': '
', 'mid-R': ' ', 'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
def printBoard(board):
print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R'])
print('-+-+-')
print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R'])
print('-+-+-')
print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R'])
turn = 'X'
for i in range(9):
❶ printBoard(theBoard)
print('Turn for ' + turn + '. Move on which space?')
❷ move = input()
❸ theBoard[move] = turn
❹ if turn == 'X':
turn = 'O'
else:
turn = 'X'
printBoard(theBoard)
5.3.2 嵌套的字典和列表
allGuests = {'Alice': {'apples': 5, 'pretzels': 12},
'Bob': {'ham sandwiches': 3, 'apples': 2},
'Carol': {'cups': 3, 'apple pies': 1}}
def totalBrought(guests, item):
numBrought = 0
❶ for k, v in guests.items():
❷ numBrought = numBrought + v.get(item, 0)
return numBrought
print('Number of things being brought:')
print(' - Apples ' + str(totalBrought(allGuests, 'apples')))
print(' - Cups ' + str(totalBrought(allGuests, 'cups')))
print(' - Cakes ' + str(totalBrought(allGuests, 'cakes')))
print(' - Ham Sandwiches ' + str(totalBrought(allGuests, 'ham sandwiches')))
print(' - Apple Pies ' + str(totalBrought(allGuests, 'apple pies')))