【python 让繁琐工作自动化】第5章 字典和结构化数据
使用Python进行数据清洗和可视化,提升工作效率 #生活技巧# #工作学习技巧# #数字技能提升#
Automate the Boring Stuff with Python: Practical Programming for Total Beginners (2nd Edition)
Written by Al Sweigart.
The second edition is available on 2019.10.29
5.1 字典数据类型
与列表一样,字典也是许多值的集合。但是与列表索引不同,字典索引可以使用许多不同的数据类型,而不仅仅是整数。字典的索引称为键(keys),键及其关联的值称为键-值对(key-value pair)。
在代码中,字典输入时带花括号 {}。
>>> myCat = {'size': 'fat', 'color': 'gray', 'disposition': 'loud'} >>> 'My cat has ' + myCat['color'] + ' fur.' 'My cat has gray fur.' >>> spam = {12345: 'Luggage Combination', 42: 'The Answer'} >>> spam[12345]) 'Luggage Combination' 123456
字典 myCat 的键是 ‘size’、‘color’ 和 ‘disposition’。这些键相应的值是 ‘fat’、‘gray’ 和 ‘loud’。可以通过它们的键访问这些值。
字典和列表与列表不同,字典中的项是不排序的。一个名为 spam 的列表中的第一项是 spam[0]。但是字典里没有“第一个”表项。虽然表项的顺序对于确定两个列表是否相同很重要,但是在字典中输入键-值对的顺序并不重要。
>>> spam = ['cats', 'dogs', 'moose'] >>> bacon = ['dogs', 'moose', 'cats'] >>> spam == bacon False >>> eggs = {'name': 'Zophie', 'species': 'cat', 'age': '8'} >>> ham = {'species': 'cat', 'age': '8', 'name': 'Zophie'} >>> eggs == ham True 12345678
因为字典是不排序的,所以不能像列表那样切片。
尝试访问字典中不存在的键,将导致 KeyError 出错信息。
spam = {'name': 'Zophie', 'age': 7} c = spam['color'] # 报错:KeyError: 'color' 12
例,利用字典保存生日数据:
birthdays = {'Alice': 'Apr 1', 'Bob': 'Dec 12', 'Carol': 'Mar 4'} while True:print('Enter a name: (blank to quit)')name = input()if name == '':breakif 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] = bdayprint('Birthday database updated.')
12345678910111213141516 keys()、values() 和 items() 方法keys()、values() 和 items() 三种字典方法将返回类似列表的值,分别对应于字典的键、值和键-值对。这些方法返回的值不是真正的列表:它们不能被修改,也没有 append() 方法。但这些数据类型 (分别为 dict_keys、dict_values 和 dict_items) 可以在 for 循环中使用。
spam = {'color': 'red', 'age': 42} print(spam.values()) # 打印 dict_values(['red', 42]) for v in spam.values():print(v) print(spam.keys()) # 打印 dict_keys(['color', 'age']) for k in spam.keys():print(k) print(spam.items()) # 打印 dict_items([('color', 'red'), ('age', 42)]) for i in spam.items():print(i) # 使用 list() 函数可以从这些方法中得到真正的列表 print(list(spam.keys())) # 打印 ['color', 'age'] # 使用多重赋值的技巧 for k, v in spam.items():print('Key: ' + k + ' Value: ' + str(v))
12345678910111213141516171819 检查键或值是否存在于字典中可以使用 in 和 not in 操作符来查看某个键或值是否存在于字典中。
>>> spam = {'name': 'Zophie', 'age': 7} >>> 'name' in spam.keys() True >>> 'Zophie' in spam.values() True >>> 'color' in spam.keys() False >>> 'color' not in spam.keys() True >>> 'color' in spam False 1234567891011
如果想要检查一个值是否为字典中的键,可以用关键字 in(或 not in),作用于该字典本身。
get() 方法字典有一个 get() 方法,它有两个参数:要检索的值的键,以及当键不存在时,返回的备用值。
picnicItems = {'apples': 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.' 123
如果没有使用get(),当键不存在时,代码会导致错误消息。
print('I am bringing ' + str(picnicItems['eggs']) + ' eggs.') # 报错:KeyError: 'eggs' 1 setdefault() 方法
常常需要为字典中某个键设置一个默认值,仅当该键没有任何值时使用它。代码看起来像这样:
spam = {'name': 'Pooka', 'age': 5} if 'color' not in spam: spam['color'] = 'black' 123
setdefault() 方法在一行代码中实现上面的代码。传递给方法的第一个参数是要检查的键,第二个参数是要在该键不存在时设置的值。如果键确实存在,setdefault() 方法将返回键的值。
>>> spam = {'name': 'Pooka', 'age': 5} >>> spam.setdefault('color', 'black') 'black' >>> spam {'color': 'black', 'age': 5, 'name': 'Pooka'} >>> spam.setdefault('color', 'white') 'black' >>> spam {'color': 'black', 'age': 5, 'name': 'Pooka'} 123456789
计算一个字符串中每个字符出现的次数:
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) 12345678
5.2 美观打印
如果在程序中导入 pprint 模块,就可以访问 pprint() 和 pformat() 函数,它们可以“美观打印”字典的值。如果希望字典中条目的显示比 print() 提供的更清晰时,这是很有帮助的。
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) 123456789
上面的代码运行输出看起来更干净,键也排序了。其结果如下:
{' ': 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}
1234567891011121314151617181920212223pprint() 函数在字典本身包含嵌套列表或字典时特别有用。
如果希望将美化的文本作为字符串值而不是在屏幕上显示,可以调用 pprint.pformat()。下面两行代码等价:
pprint.pprint(someDictionaryValue) print(pprint.pformat(someDictionaryValue)) 12
5.3 使用数据结构对真实世界的事物建模
可以用列表和字典对现实世界的事物建模,比如棋盘。对于第一个示例,将使用一个比国际象棋更简单的游戏:井字棋(tic-tac-toe)。
井字棋盘井字棋盘看起来像一个大的井字符号 (#),有 9 个位置,每个位置可以包含 X、O 或空。
要用字典表示棋盘,可以为每个位置分配一个字符串值的键。
键 ‘top-R’ 的字符串值可以表示右上角,键 ‘low-L’ 的字符串值可以表示左下角,键 ‘mid-M’ 的字符串值可以表示中间,依此类推。
这个字典就是表示井字棋盘的数据结构。将这个字典表示的棋盘保存在名为 theBoard 的变量中。
创建一个函数,将棋盘字典打印到屏幕上。
# ticTacToe.py 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] = turnif turn == 'X':turn = 'O'else:turn = 'X'
12345678910111213141516171819202122232425这并不是一个完整的井字棋游戏,例如,它不会检查一个玩家是否获胜,但它足以查看数据结构如何在程序中使用。
完整的井字棋游戏程序的源代码可以在 http://nostarch.com/automatestuff/ 的参考资料中找到。
例,使用包含其他字典的字典,来记录谁带了什么去野餐。totalBrought() 函数可以读取这个数据结构,计算所有客人带来的食物的总数。
allGuests = {'Alice': {'apples': 5, 'pretzels': 12}, 'Bob': {'ham sandwiches': 3, 'apples': 2}, 'Carol': {'cups': 3, 'apple pies': 1}} def totalBrought(guests, item):numBrought = 0for 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')))
123456789101112131415165.4 实践项目
奇幻游戏的库存正在创建一款奇幻电子游戏。对玩家库存建模的数据结构将是一个字典,其中键是描述库存中物品的字符串值,值是一个整数值,说明玩家拥有该物品的数量。例如,字典值 {‘rope’: 1, ‘torch’: 6, ‘gold coin’: 42, ‘dagger’: 1, ‘arrow’: 12} 表示玩家有 1 根绳子,6 支火炬,42 枚金币,等等。
编写一个名为 displayInventory() 的函数,该函数将接受任何可能的“库存”并如下所示:
Inventory:
12 arrow
42 gold coin
1 rope
6 torch
1 dagger
Total number of items: 62
提示:可以使用for循环遍历字典中的所有键。
# inventory.py stuff = {'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, 'arrow': 12} def displayInventory(inventory): print("Inventory:") item_total = 0 for k, v in inventory.items(): # FILL IN THE CODE HERE print("Total number of items: " + str(item_total)) displayInventory(stuff) 1234567891011
解:文件 inventory.py 的代码如下:
# inventory.py stuff = {'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, 'arrow': 12} def displayInventory(inventory): print("Inventory:") item_total = 0 for k, v in inventory.items(): print(str(v) + ' ' + k) item_total += v print("Total number of items: " + str(item_total)) displayInventory(stuff) 123456789101112 列表到字典的函数,用于奇幻游戏的库存
想象一下,一条被击败的龙的战利品表示为这样的字符串列表:
dragonLoot = [‘gold coin’, ‘dagger’, ‘gold coin’, ‘gold coin’, ‘ruby’]
编写一个名为 addToInventory(inventory, addedItems) 的函数,其中 inventory 参数是一个代表玩家库存的字典(如前一个项目中所示),而 addedItems 参数是一个类似 dragonLoot 的列表。addToInventory() 函数应该返回一个表示已更新库存的字典。注意,addedItems 列表可以包含多个同样的项。代码可能是这样的:
def addToInventory(inventory, addedItems): # your code goes here inv = {'gold coin': 42, 'rope': 1} dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby'] inv = addToInventory(inv, dragonLoot) displayInventory(inv) 1234567
前一个程序(使用前一个项目中的 displayInventory() 函数)将输出以下内容:
Inventory:
45 gold coin
1 rope
1 ruby
1 dagger
Total number of items: 48
def addToInventory(inventory, addedItems): for item in addedItems:count = inventory.setdefault(item, 0)inventory[item] = count + 1 return inventory inv = {'gold coin': 42, 'rope': 1} dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby'] inv = addToInventory(inv, dragonLoot) displayInventory(inv) 12345678910
学习网站:
https://automatetheboringstuff.com/chapter5/
网址:【python 让繁琐工作自动化】第5章 字典和结构化数据 https://www.yuejiaxmz.com/news/view/386311
相关内容
Python编程快速上手让繁琐工作自动化Python 自动化指南(繁琐工作自动化)第二版:四、列表
解决Python编程快速上手——让繁琐工作自动化的具体操作步骤
Python自动化任务
数据清洗:自动化工具与手动清理的结合
Python自动化办公学习路线:提升工作效率,释放副业可能,让生活更美好!
Python报表自动化
让生活自动化的5个Python项目:从初级到高级
构建工作流自动化的 5 个最佳工具
高效Python工作流自动化:简化开发流程的最佳实践