文章目录
06-python中的集合类-02-ChainMap
今天 我们继续讲解 Collections 中的 其他的数据结构 ChainMap
, 看这个名称 大概也能知道 是做什么的?
就是把多个字典拉成一个Chain的形式。
namedtuple() | factory function for creating tuple subclasses with named fields |
---|---|
deque | list-like container with fast appends and pops on either end |
ChainMap | dict-like class for creating a single view of multiple mappings |
Counter | dict subclass for counting hashable objects |
OrderedDict | dict subclass that remembers the order entries were added |
defaultdict | dict subclass that calls a factory function to supply missing values |
UserDict | wrapper around dictionary objects for easier dict subclassing |
UserList | wrapper around list objects for easier list subclassing |
UserString | wrapper around string objects for easier string subclassing |
ChainMap 的使用
chainmap 就是把一些 字典 放在一个 chain 里面, 逻辑上 感觉 像是一个字典一样使用, 其实内部做了一个 maps 的属性, 把字典放在 一个list 里面了。
ChainMap 的使用场景: 有多个字典或者映射,你想将它们从逻辑上合并为一个单一的映射后执行某些操作
from collections import ChainMap
a = {"x": 1, "z": 3}
b = {"y": 2, "z": 4}
c = {"y": 20, "z": 30, "x": 10, "p": 66}
chain = ChainMap(a, b, c)
print(chain)
在新生成的chain 中 你几乎可以把它当做一个字典使用。 比如 去 chain['x']
,chain.get('y')
这里有一个maps 的属性, 这里就是存放所有的字典的一个list , 当取字典中的key 的时候, 他会先去第一个字典查找 如果有 就直接返回,如果没有就到第二字典里面去找,以此类推,之后找完maps 后都没有, 要么返回None, 要么报错。
举个例子
>>> from collections import ChainMap
>>> chain
ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4}, {'y': 20, 'z': 30, 'x': 10, 'p': 66})
>>> chain.get('y')
2
>>> chain.get('z')
3
>>>
>>>
>>> chain['x']
1
>>> chain['z']
3
>>> chain['name']
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/collections/__init__.py", line 916, in __getitem__
return self.__missing__(key) # support subclasses that define __missing__
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/collections/__init__.py", line 908, in __missing__
raise KeyError(key)
KeyError: 'name'
当取 key=‘y’ 的时候, 第二字典里有,直接返回。
当取 key=‘z’ 的时候 这三个字典 都有 那么就看谁在前面就取谁。 第一个字典中就有 所以返回是 3 。
ChainMap 只是把字典 逻辑上连接在一起 方便 我们当成一个字典使用。
比如判断 key 是否在 这几个字典中,
ChainMap 删除 增加元素
注意:
于字典的更新或删除操作总是影响的是列表中第一个字典
>>> chain
ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4}, {'y': 20, 'z': 30, 'x': 10, 'p': 66})
>>> chain['name']='frank'
>>> chain
ChainMap({'x': 1, 'z': 3, 'name': 'frank'}, {'y': 2, 'z': 4}, {'y': 20, 'z': 30, 'x': 10, 'p': 66})
>>> # 删除元素
>>> chain.pop('x')
1
>>> chain
ChainMap({'z': 3, 'name': 'frank'}, {'y': 2, 'z': 4}, {'y': 20, 'z': 30, 'x': 10, 'p': 66})
如果 你想删除 第二个字典的元素 会失败, 比如我想删除,key=‘y’ 的键值对时,就会报错。
>>> chain
ChainMap({'z': 3, 'name': 'frank'}, {'y': 2, 'z': 4}, {'y': 20, 'z': 30, 'x': 10, 'p': 66})
>>> chain.pop('y')
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/collections/__init__.py", line 984, in pop
return self.maps[0].pop(key, *args)
KeyError: 'y'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/collections/__init__.py", line 986, in pop
raise KeyError('Key not found in the first mapping: {!r}'.format(key))
KeyError: "Key not found in the first mapping: 'y'"
对于删除 ,增加 键值对 都是对第一个 字典 进行的。 对于查找 是可以 查找所有的字典。
来看下例子
>>> chain
ChainMap({'z': 3, 'name': 'frank'}, {'y': 2, 'z': 4}, {'y': 20, 'z': 30, 'x': 10, 'p': 66})
>>> 'p' in chain
True
查找元素 会安装 chainmap 顺序 去查找, 因为p 是在第三个字典中的,所以返回True
ChainMap 中加入一个新的字典
在chainmap 中加入一个新的字典, 可以使用 new_child 方法 加入一个字典
from collections import ChainMap
one = {'one': 1}
two = {'two': 2}
three = {'three': 3}
chain = ChainMap(one, two)
print(chain)
chain2 = chain.new_child(three)
在控制台里演示一下
>>> from collections import ChainMap
...
... one = {'one': 1}
... two = {'two': 2}
... three = {'three': 3}
... # four = {'four': 4}
>>>
>>>
>>> chain = ChainMap(one, two)
>>> chain
ChainMap({'one': 1}, {'two': 2})
>>> chain.new_child(three)
ChainMap({'three': 3}, {'one': 1}, {'two': 2})
会返回一个chainMap 并且 最新加入的字典会放在 第一个位置,看例子。
ChainMap 中 获取parents
ChainMap 中有一个属性, parents , 用来获取除去第一个位置的元素 后面的 所有元素
>>> from collections import ChainMap
...
... one = {'one': 1}
... two = {'two': 2}
... three = {'three': 3}
... four = {'four': 4}
...
... chain = ChainMap(one, two,three,four)
>>>
>>>
>>> chain
ChainMap({'one': 1}, {'two': 2}, {'three': 3}, {'four': 4})
>>> chain.parents
ChainMap({'two': 2}, {'three': 3}, {'four': 4})
>>> chain.parents.parents
ChainMap({'three': 3}, {'four': 4})
也就是 以第一个位置是 child , 第二个位置是parent, 第三个位置是 第二位置的parent
总结
本文主要总结 ChainMap 的一些特点, 我平常对这个结构用的比较少。 以后可以多用一下 标准库中提供这个 类型,方便我们提高开发效率。