Python v3.7.0
合并字典
- 使用字典对象内置的update方法
profile = {"name": "foo", "age": 3}
ext_info = {"gender": "male", "age": 4}
profile.update(ext_info)
# profile.update((ext_info, ext_info1, ... )) # 合并多个字典
# full_profile = profile.update(ext_info) # update方法没有返回值,full_profile为None
使用这种方法,如果出现重复键,那么最后一次出现的映射值会被返回。在上面的例子中,profile['age']的结果为4.
使用字典的update方法,其本质是浅拷贝,若不想更新原字典,可以借助深拷贝,如下:
from copy import deepcopy
full_profile = deepcopy(profile)
full_profile.update((ext_info1, ext_info2 ))
- 先解包在合并字典
profile = {"name": "foo", "age": 3}
ext_info = {"address": "test"}
full_profile = dict(**profile, **ext_info)
如果两个要合并的字典中有相同的Key,使用此方法会报错:TypeError: type object got multiple values for keyword argument 'age'
- 借助collections.ChainMap
现在假设我们必须在两个字典中执行查找操作(比如先从a中找,如果找不到再在b中找),那么使用ChainMap
是最合适的。
ChainMap
接受多个字典并将它们在逻辑上变为一个字典,这些字典并不是真的合并在一起了,ChainMap
类只是在内部创建了一个容纳这些字典的列表并重新定义了一些常见的字典操作来遍历这个列表。
from collections import ChainMap
profile = {"name": "foo", "age": 3}
ext_info = {"address": "test", "gender": "male", "age": 5}
full_profile = ChainMap(profile, ext_info)
print(full_profile)
print(full_profile['age'])
>>>
ChainMap({'name': 'foo', 'age': 3}, {'address': 'test', 'gender': 'male', 'age': 5})
3
要注意打印full_profile['age']
的结果是3,而如果使用update方法合并这两个字典,结果将会是5。也就是说如果出现重复键,那么第一次出现的映射值会被返回。
同时,由于ChainMap
使用原来的字典,它自己不创建新的字典,所以当原字典做了更新,ChainMap
对象也会自动更新。
ext_info['gender'] = 'famale'
print(full_profile ['gender'])
>>>
famale
大部分字典操作都是可以正常使用的,比如:
length = len(full_profile)
keys = list(full_profile.keys())
values = list(full_profile.values())
对于字典的更新或删除操作总是影响的是列表中第一个字典:
full_profile["email"] = "test@foxmail.com"
print(profile)
del full_profile['gender'] # 会报错,profile字典中不存在'gender'
>>>
{'name': 'foo', 'age': 3, 'email': 'test@foxmail.com'}
KeyError: "Key not found in the first mapping: 'gender'"
如果需要深度写和删除,也可以很容易的通过定义一个子类来实现:
class DeepChainMap(ChainMap):
'Variant of ChainMap that allows direct updates to inner scopes'
def __setitem__(self, key, value):
for mapping in self.maps:
if key in mapping:
mapping[key] = value
return
self.maps[0][key] = value
def __delitem__(self, key):
for mapping in self.maps:
if key in mapping:
del mapping[key]
return
raise KeyError(key)
>>> d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})
>>> d['lion'] = 'orange' # update an existing key two levels down
>>> d['snake'] = 'red' # new keys get added to the topmost dict
>>> del d['elephant'] # remove an existing key one level down
>>> d # display result
DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})
查找两字典的相同点
怎样在两个字典中寻找相同点,比如相同的键、相同的值等?比较Pythonic的方法是直接在字典的keys()
或者items()
方法的返回结果上执行集合操作。
a = {"x": 1, "y": 2, "z": 3}
b = {"w": 11, "y": 2, "z": 33}
# Find keys in common
common_keys = a.keys() & b.keys() # {'y', 'z'}
# Find keys in a that are not in b
diff = a.keys() - b.keys() # {'x'}
# Find (key,value) pairs in common
common_pair = a.items() & b.items() # {('y', 2)}
这些操作也可以用于修改或者过滤字典元素。比如,假如你想以现有字典构造一个
排除几个指定键的新字典。下面利用字典推导来实现这样的需求:
c = {k: a[k] for k in a.keys() - {"x", "y"}} # {'z': 3}
注意,字典的value
方法它并不支持上面说的的集合操作,这是因为不能保证字典中的值是互不相同的。
网友评论