使用ChainMap

使用ChainMap

最近看到組內有小夥伴在處理在多個dict內順序查找元素的時候,用了ChainMap,有意思。場景: 當用戶輸入一個產品id的時候,你但願能正在出售的產品,或在已過時的產品中查找。python

你能夠實現:git

g_expire_products = {
    1: {'name': 'nike shoes', 'price': 30}, 
    2: {'name': 'box', 'price': 2},
}
g_on_sale_products = {
    3: {'name': 'adidas shoes', 'price': 25},
    4: {'name': 'tee', 'price': 2},
}

def get_product(id):
    return g_on_sale_products.get(id, g_expire_products.get(id))

若是是不止已過時產品,但願在其餘庫房的產品也能被查找,你可能還要在一個新的dict裏面查找。github

這不難實現,就是代碼看起來有點難看。
爲什麼不試下ChainMap,用ChainMap能夠這樣寫:app

g_products = ChainMap(g_on_sale_products, g_expire_products)

def get_product(id):
    return g_products.get(id)

ChainMap能夠添加多個dict,至關於把你的if-else判斷作了抽象。ide

ChainMap源碼

ChainMap源碼在這兒code

能夠看下__init__orm

def __init__(self, *maps):
    '''Initialize a ChainMap by setting *maps* to the given mappings.
    If no mappings are provided, a single empty dictionary is used.
    '''
    self.maps = list(maps) or [{}]          # always at least one map

這裏傳入多個dict後,多個dict放在maps裏,這裏maps傳的是多個dict的引用,也就是它沒有拷貝內存。內存

那麼它是如何查找key的,咱們來看下:get

def __missing__(self, key):
    raise KeyError(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__

def get(self, key, default=None):
    return self[key] if key in self else default

def __contains__(self, key):
    return any(key in m for m in self.maps)

能夠看到,當經過dict[key]的時候,它是從self.maps裏的存的dict,從前日後找,初始化的時候,第一個dict先被查找,key不在第一個dict的時候,就會找下一個dict裏查找。源碼

不過它在修改的時候,是這樣作的

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

def __delitem__(self, key):
    try:
        del self.maps[0][key]
    except KeyError:
        raise KeyError('Key not found in the first mapping: {!r}'.format(key))

也就是你修改其中一個key的時候,它會在第一個dict裏面修改,刪除一個key時候也是。

因此通常使用ChainMap的時候,我以爲最好不要作修改,由於修改是基於你初始化的時候,傳入的dict的順序,每次若是初始化的時候,若是dict的順序不肯定,你每次就不能肯定會修改哪個dict。

相關文章
相關標籤/搜索