使用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。

相关文章
相关标签/搜索