资讯专栏INFORMATION COLUMN

使用ChainMap

EscapedDog / 3252人阅读

摘要:使用最近看到组内有小伙伴在处理在多个内顺序查找元素的时候,用了,有意思。场景当用户输入一个产品的时候,你希望能正在出售的产品,或在已过期的产品中查找。

使用ChainMap

最近看到组内有小伙伴在处理在多个dict内顺序查找元素的时候,用了ChainMap,有意思。场景: 当用户输入一个产品id的时候,你希望能正在出售的产品,或在已过期的产品中查找。

你可以实现:

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里面查找。

这不难实现,就是代码看起来有点难看。
为何不试下ChainMap,用ChainMap可以这样写:

g_products = ChainMap(g_on_sale_products, g_expire_products)

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

ChainMap可以添加多个dict,相当于把你的if-else判断做了抽象。

ChainMap源码

ChainMap源码在这儿

可以看下__init__

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的,我们来看下:

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。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43610.html

相关文章

  • Python每日一练0013

    摘要:问题现在有多个字典或者映射,你想将它们从逻辑上合并为一个单一的映射后执行某些操作,比如查找值或者检查某些键是否存在。 问题 现在有多个字典或者映射,你想将它们从逻辑上合并为一个单一的映射后执行某些操作, 比如查找值或者检查某些键是否存在。 解决方案 使用collections库的ChainMap类,可以快速的将多个dict合并在一起 >>> from collections impor...

    sihai 评论0 收藏0
  • Python中collections模块的使用

    摘要:这里提示一下,有些函数对队列进行操作,但返回值是,比如反转队列,将队列中元素向右移位,尾部的元素移到头部。比如字典中的键映射多个值输出结果如下三用途创建命名字段的元组。四用途统计可哈希的对象。 本文将详细讲解collections模块中的所有类,和每个类中的方法,从源码和性能的角度剖析。 一个模块主要用来干嘛,有哪些类可以使用,看__init__.py就知道 This module i...

    antyiwei 评论0 收藏0
  • Python中collections模块的使用

    摘要:这里提示一下,有些函数对队列进行操作,但返回值是,比如反转队列,将队列中元素向右移位,尾部的元素移到头部。比如字典中的键映射多个值输出结果如下三用途创建命名字段的元组。四用途统计可哈希的对象。 本文将详细讲解collections模块中的所有类,和每个类中的方法,从源码和性能的角度剖析。 一个模块主要用来干嘛,有哪些类可以使用,看__init__.py就知道 This module i...

    xorpay 评论0 收藏0
  • Python中collections模块的使用

    摘要:这里提示一下,有些函数对队列进行操作,但返回值是,比如反转队列,将队列中元素向右移位,尾部的元素移到头部。比如字典中的键映射多个值输出结果如下三用途创建命名字段的元组。四用途统计可哈希的对象。 本文将详细讲解collections模块中的所有类,和每个类中的方法,从源码和性能的角度剖析。 一个模块主要用来干嘛,有哪些类可以使用,看__init__.py就知道 This module i...

    ASCH 评论0 收藏0
  • Python中collections模块的使用

    摘要:这里提示一下,有些函数对队列进行操作,但返回值是,比如反转队列,将队列中元素向右移位,尾部的元素移到头部。比如字典中的键映射多个值输出结果如下三用途创建命名字段的元组。四用途统计可哈希的对象。 本文将详细讲解collections模块中的所有类,和每个类中的方法,从源码和性能的角度剖析。 一个模块主要用来干嘛,有哪些类可以使用,看__init__.py就知道 This module i...

    sf190404 评论0 收藏0

发表评论

0条评论

EscapedDog

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<