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
>>>

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM