Python 中的 dict 类提供了许多处理字典的实用方法。其中一些已经在 dict 的概念中介绍过。这里我们再介绍几个,以及一些遍历和操作字典的技巧。
<dict>.setdefault() 会自动添加键,而不会抛出 KeyError。<dict>.fromkeys(<iterable>, <default value>) 可以从任意数量的可迭代对象创建一个新的 dict。<dict>.keys()、<dict>.values() 和 <dict>.items() 提供了方便的迭代器。sorted(<dict>.items()) 可以轻松地对 dict 中的条目重新排序。<dict_one>.update(<dict_two>) 用另一个 dict 中重叠的值来更新一个 dict。<dict> | <other_dict> 和 <dict> |= <other_dict> 通过运算符合并或更新两个 dict。reversed(<dict>.keys())、reversed(<dict>.values()) 或 reversed(<dict>.items()) 会生成_反向_视图。<dict>.popitem() 移除并返回一对 key、value。setdefault() 实现无错误的插入字典的概念之前讲过,<dict>.get(<key>, <default value>) 会返回已有的 value,如果字典中找不到 key,则返回 default value,从而避免 KeyError。在你不想添加额外的错误处理,但又无法确定要查找的 key 一定存在时,这种方式就很合适。
对于同样“安全”(不会出现 KeyError)的插入操作,可以使用 <dict>.setdefault(<key>, <default value>) 方法。如果字典中能找到 key,<dict>.setdefault(<key>, <default value>) 就会返回对应的 value。如果没有找到这个键,它就会_插入_(key、default value)这一对,并返回 default value 供使用。
>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'}
# Looking for the value associated with key "Rock Brown".The key does not exist,
# so it is added with the default value, and the value is returned.
>>> palette.setdefault('Rock Brown', '#694605')
'#694605'
# The (key, default value) pair has now been added to the dictionary.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'}
fromkeys() 从可迭代对象填充字典要用各种 keys 和默认值快速填充字典,可以使用_类方法_ fromkeys(<iterable>, <default value>),它会遍历由 keys 组成的可迭代对象,并创建一个新的 dict。所有 values 都会被设为所提供的 default value:
>>> new_dict = dict.fromkeys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'], 'fill in hex color here')
{'Grassy Green': 'fill in hex color here',
'Purple Mountains Majesty': 'fill in hex color here',
'Misty Mountain Pink': 'fill in hex color here'}
.popitem() 移除并返回一个键值对.popitem() 会从字典中移除并返回单个(key、value)对。这些对按后进先出(LIFO)的顺序返回。如果字典为空,调用 popitem() 会抛出 KeyError:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_I.popitem()
('Misty Mountain Pink', '#f9c5bd')
>>> palette_I.popitem()
('Purple Mountains Majesty', '#8076a3')
>>> palette_I.popitem()
('Grassy Green', '#9bc400')
# All (key, value) pairs have been removed.
>>> palette_I.popitem()
Traceback (most recent call last):
line 1, in <module>
palette_I.popitem()
KeyError: 'popitem(): dictionary is empty'
.keys()、.values() 和 .items() 方法会返回字典的可迭代视图。
可以借助这些视图轻松地遍历条目,而不会改动它们。视图还是_动态_的:当底层字典数据变化时,关联的 view object 也会随之变化:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
# Using .keys() returns a list of keys.
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'])
# Using .values() returns a list of values.
>>> palette_I.values()
dict_values(['#9bc400', '#8076a3', '#f9c5bd'])
# Using .items() returns a list of (key, value) tuples.
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')])
# Views are dynamic. Changing values in the dict
# changes all of the associated views.
>>> palette_I['Purple Mountains Majesty'] = (128, 118, 163)
>>> palette_I['Deep Red'] = '#932432'
>>> palette_I.values()
dict_values(['#9bc400', (128, 118, 163), '#f9c5bd', '#932432'])
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'Deep Red'])
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')])
.keys()、.values() 和 .items() 的更多内容在 Python 3.7+ 中,dicts 会保留条目的插入顺序,因此使用 .keys()、.values() 或 .items() 遍历时,可以按先进先出(FIFO)的顺序进行。
在 Python 3.8+ 中,视图还是_可反转的_。这样就可以用 reversed(<dict>.keys())、reversed(<dict>.values()) 或 reversed(<dict>.items()),按后进先出(LIFO)的顺序遍历键、值或(key、value)对:
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
>>> for item in palette_II.items():
... print(item)
...
('Factory Stone Purple', '#7c677f')
('Green Treeline', '#478559')
('Purple baseline', '#161748')
>>> for item in reversed(palette_II.items()):
... print(item)
...
('Purple baseline', '#161748')
('Green Treeline', '#478559')
('Factory Stone Purple', '#7c677f')
.update() 合并字典可以用 <dict_one>.update(<dict_two>) _合并_两个字典。这个方法会取出 <dict_two> 的(key,value)对,并把它们写入 <dict_one>:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple Baseline': '#161748'}
>>> palette_I.update(palette_II)
# Note that new items from palette_II are added.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'}
当两个字典中的键_重叠_时,dict_one 中的 value 会被 dict_two 中对应的 value 覆盖:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
>>> palette_III = {'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189)}
>>> palette_I.update(palette_III)
# Overlapping values in palette_I are replaced with
# values from palette_III
>>> palette_I
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559', 'Purple baseline': '#161748'}
| 和 |=)运算符合并或更新字典Python 3.9 引入了另一种合并 dicts 的方式:union 运算符。dict_one | dict_two 会创建一个新字典,由 dict_one 和 dict_two 的(key、value)对组成。当两个字典有相同的键时,dict_two 的值优先。
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
>>> new_dict = palette_I | palette_II
>>> new_dict
...
{'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
dict_one |= other 的行为类似于 <dict_one>.update(<other>),不过在这种情况下,other 既可以是 dict,也可以是由(key、value)对组成的可迭代对象:
>>> palette_III = {'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189)}
>>> new_dict |= palette_III
>>> new_dict
...
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
字典没有内置的排序方法。不过,可以用内置函数 sorted() 配合 .items() 对 dict 的_视图_进行排序。然后可以用排序后的视图创建一个新字典。除非指定了_排序键_,否则默认按字典的 keys 排序。
# Default ordering for a dictionary is last in, first out (LIFO).
>>> color_palette = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
# The default sort order for a dictionary uses the keys.
>>> sorted_palette = dict(sorted(color_palette.items()))
>>> sorted_palette
{'Factory Stone Purple': '#7c677f',
'Grassy Green': '#9bc400',
'Green Treeline': '#478559',
'Misty Mountain Pink': '#f9c5bd',
'Purple Mountains Majesty': '#8076a3',
'Purple baseline': '#161748'}
# A sort key can be provided in the form
# of an anonymous function (lambda).
>>> value_sorted_palette = dict(sorted(color_palette.items(), key=lambda color: color[1]))
>>> value_sorted_palette
{'Purple baseline': '#161748',
'Green Treeline': '#478559',
'Factory Stone Purple': '#7c677f',
'Purple Mountains Majesty': '#8076a3',
'Grassy Green': '#9bc400',
'Misty Mountain Pink': '#f9c5bd'}
在字典中可靠地交换键和值需要花点功夫,但可以通过使用 dict.items() 的 loop,或用字典推导式来实现。安全的交换假定 dict 的键和值都是_可哈希的_。
color_reference = {'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
# Creating a new dictionary to hold the swapped entries.
>>> swapped_color_reference = {}
# Iterating through the dictionary, using values as keys.
>>> for key, value in color_reference.items():
... swapped_color_reference[value] = key
>>> swapped_color_reference
{'#8076a3': 'Purple Mountains Majesty',
'#f9c5bd': 'Misty Mountain Pink',
'#7c677f': 'Factory Stone Purple',
'#478559': 'Green Treeline',
'#161748': 'Purple baseline'}
# A dictionary comprehension can also be used to swap entries.
>>> swapped = {value: key for key, value in
color_reference.items()}
>>> swapped
{'#8076a3': 'Purple Mountains Majesty',
'#f9c5bd': 'Misty Mountain Pink',
'#7c677f': 'Factory Stone Purple',
'#478559': 'Green Treeline',
'#161748': 'Purple baseline'}
如果 dict 中存储的值不唯一,那么在交换键和值之前,就需要做额外的检查:
# Things become more complicated if there are duplicates in
# potential key values.This dict is arranged by hex, RGB, and HSL
# keys, but values repeat.
>>> extended_colors = {'#8076a3': 'Purple Mountains Majesty',
(128, 118, 163): 'Purple Mountains Majesty',
(21, 28, 0, 36): 'Purple Mountains Majesty',
'#f9c5bd': 'Misty Mountain Pink',
(249, 197, 189): 'Misty Mountain Pink',
(0, 21, 24, 2): 'Misty Mountain Pink',
'#7c677f': 'Factory Stone Purple',
(124, 103, 127): 'Factory Stone Purple',
(2, 19, 0, 50): 'Factory Stone Purple',
'#478559': 'Green Treeline',
(71, 133, 89): 'Green Treeline',
(47, 0, 33, 48): 'Green Treeline'}
# New empty dictionary for holding swapped entries.
>>> consolidated_colors = {}
# Iterating over (key, value) pairs using .items()
>>> for key, value in extended_color_reference.items():
... if value in consolidated_colors: # <--Check if key has already been created.
... consolidated_colors[value].append(key)
... else:
... consolidated_colors[value] = [key] # <--Create a value list with the former key in it.
>>> consolidated_colors
{'Purple Mountains Majesty': ['#8076a3', (128, 118, 163), (21, 28, 0, 36)],
'Misty Mountain Pink': ['#f9c5bd', (249, 197, 189), (0, 21, 24, 2)],
'Factory Stone Purple': ['#7c677f', (124, 103, 127), (2, 19, 0, 50)],
'Green Treeline': ['#478559', (71, 133, 89), (47, 0, 33, 48)]}
如果想详细了解字典以及处理字典的方法,官方教程和官方库参考是很好的起点。
Real Python 和 Finxter 也有关于 Python 字典的非常详尽的文章。
想了解更多排序相关内容,请参阅 Python 文档中的 Sorting HOW TO。