代码之家  ›  专栏  ›  技术社区  ›  Kai

Python列表理解中的缓存值

  •  5
  • Kai  · 技术社区  · 15 年前

    我使用以下列表:

    resources = [obj.get("file") for obj in iterator if obj.get("file") != None]
    

    有没有办法“缓存”的值 obj.get("file") 当它签入if语句时,它就不必调用 get 当obj生成返回列表时,是否再次在obj上?

    4 回复  |  直到 15 年前
        1
  •  10
  •   Jon-Eric    15 年前
    resources = filter(None, (obj.get("file") for obj in iterator))
    

    有关详细信息,请参阅文档 filter None 对于函数(如上所述),过滤掉所有不正确的值。

    如果obj.get()返回一个具有 __nonzero__ 方法,然后您需要通过 lambda obj: obj != None 以获得与原始代码完全相同的结果。

        2
  •  5
  •   nikow    15 年前

    filter 您可以简单地使用:

    resources = [file_obj
                 for file_obj in (obj.get("file") for obj in iterator)
                 if file_obj is not None]
    
        3
  •  1
  •   SingleNegationElimination    15 年前

    试着这样做:

    resources = filter( lambda x: x is not None, [obj.get("file") for ob jin iterator])
    
        4
  •  1
  •   jakecard    15 年前

    创建一个临时dict来保存值。然后,创建一个将此dict用作缓存的函数,并在列表理解中使用该函数,如下所示:

    obj_cache = {}
    
    def cache_get (target, key):
        if (target, key) not in obj_cache: obj_cache[(target, key)] = target.get(key)
        return obj_cache[(target, key)]
    
    resources = [cache_get(obj, "file") for obj in iterator if cache_get(obj, "file") != None]
    

    此外,您可能已经知道这一点(如果知道,请忽略此答案),但除非obj.get(“文件”)正在进行数据库调用、打开文件、通过网络发出请求或执行其他可能昂贵的操作,否则每次迭代调用两次而不是一次可能是无害的,因为您只需要在成本中添加O(n)。

        5
  •  -2
  •   Georgy rassa45    4 年前

    从Python3.8开始,可以使用 assignment expression 要避免调用函数两次,请执行以下操作:

    iterator = [{'file': 'abc'}, 
                {'file': None}, 
                {'file': 'def'}, 
                {'file': None}]
    res = [file for obj in iterator 
           if (file := obj.get("file")) is not None]
    print(res)
    # ['abc', 'def']