python collections模块 之 ChainMap

ChainMap提供了一种多个字典整合的方式,它没有去合并这些字典,而是将这些字典放在一个 maps (一个列表)里,内部实现了很多 dict 的方法,大部分 dict 的方法,ChainMap 都能使用。

ChainMap在获取一个key的值时,会遍历 maps ,一旦在其中一个 字典里找到了这个 key ,便停止寻找,源码如下:

    def __getitem__(self, key):
        for mapping in self.maps:
            try:
                return mapping[key]             # can't use 'key in mapping' with defaultdict
            except KeyError:
                pass
        return self.__missing__(key)            # support subclasses that define __missing__

例子:

a = {'x': 1, 'z': 3 }
b = {'y': 2, 'z': 4 }
from collections import ChainMap
c = ChainMap(a,b)
print(c['x']) # Outputs 1 (from a)
print(c['y']) # Outputs 2 (from b)
print(c['z']) # Outputs 3 (from a)

当设置 ChainMap 的某个key时,只能在第一个字典里寻找这个key,找到则更新,没找到则设置,源码如下:

    def __setitem__(self, key, value):
        self.maps[0][key] = value

例:

c['z'] = 5
c['g'] = 2

print(a) # output: {'x': 1, 'z': 5, 'g': 5  }

print(b) # output: {'y': 2, 'z': 4}

删除某个key时,也是一样,只会在第一个dict中寻找这个key,如果没有找到会报错 KeyError

其他方法:

new_child(self, m=None):

从左边加入,若 m=None,则在左边加入一个空的 dict

源码如下:

    def new_child(self, m=None):                # like Django's Context.push()
        '''New ChainMap with a new map followed by all previous maps.
        If no map is provided, an empty dict is used.
        '''
        if m is None:
            m = {}
        return self.__class__(m, *self.maps)

parents(self):

删除左边的 dict 后,返回一个新的ChainMap。

    def parents(self):                          # like Django's Context.pop()
        'New ChainMap from maps[1:].'
        return self.__class__(*self.maps[1:])

作为ChainMap的替代,你可能会考虑用 update() 方法将两个字典合并,但这需要重新创建一个字典,或者破坏现有字典的结构,并且,原字典做了更新后,这种改变不会反应到新的字典中去。例:

>>> a = {'x': 1, 'z': 3 }
>>> b = {'y': 2, 'z': 4 }
>>> merged = dict(b)
>>> merged.update(a)
>>> merged['x']
1
>>> merged['y']
2
>>> merged['z']
3
>>>
>>> a['x'] = 13
>>> merged['x']
1

ChainMap 使用原来的字典,不会发生上面的情况:

>>> a = {'x': 1, 'z': 3 }
>>> b = {'y': 2, 'z': 4 }
>>> merged = ChainMap(a, b)
>>> merged['x']
1
>>> a['x'] = 42
>>> merged['x'] # Notice change to merged dicts
42
>>>

  

猜你喜欢

转载自www.cnblogs.com/BeautifulWorld/p/11712684.html