python 列表解析中如何设置局部变量?

yqyhoc1h  于 2022-12-17  发布在  Python
关注(0)|答案(8)|浏览(158)

我有一个方法,它接受一个列表并返回一个对象:

# input a list, returns an object
def map_to_obj(lst):
    a_list = f(lst)
    return a_list[0] if a_list else None

我想得到一个包含所有非None的Map元素的列表。
就像这样:

v_list = [v1, v2, v3, v4]

[map_to_obj(v) for v in v_list if map_to_obj(v)]

但是在列表解析中调用map_to_obj方法两次似乎不太好。
有没有一种方法可以让列表解析中包含局部变量,从而使其具有更好的性能?
还是编译器会自动优化它?
这是我想要的

(sml like)
[let mapped = map_to_obj(v) in for v in v_list if mapped end]
gc0ot86w

gc0ot86w1#

使用嵌套列表解析:

[x for x in [map_to_obj(v) for v in v_list] if x]

或者更好的是,围绕生成器表达式的列表解析:

[x for x in (map_to_obj(v) for v in v_list) if x]
e1xvtsh3

e1xvtsh32#

Python 3.8开始,引入了assignment expressions (PEP 572):=运算符),可以在列表解析中使用局部变量,以避免两次调用同一个函数。
在我们的示例中,我们可以将map_to_obj(v)的求值命名为变量o,同时使用表达式的结果来过滤列表;并因此使用o作为Map值:

[o for v in [v1, v2, v3, v4] if (o := map_to_obj(v))]
23c0lvtd

23c0lvtd3#

变量赋值只是一个单一的绑定:

[x   for v in l   for x in [v]]

这是一个更一般的答案,也更接近你提出的问题,所以你可以这样写:

[x   for v in v_list   for x in [map_to_obj(v)]   if x]
aiazj4mn

aiazj4mn4#

使用python内置的filter可以避免重新计算:

list(filter(lambda t: t is not None, map(map_to_obj, v_list)))
mgdq6dx1

mgdq6dx15#

一个局部变量可以在一个理解中通过欺骗一个比特和使用一个额外的'for'来设置,这个额外的. for'通过一个包含局部变量所需值的1元素元组来“迭代”。

[o for v in v_list for o in (map_to_obj(v),) if o]

这里,o是局部变量,对于每个v被设置为等于map_to_obj(v)
在我的测试中,这比Laying Dog的嵌套生成器表达式稍快一些(也比OP对map_to_obj(v)的两次调用快,令人惊讶的是,如果map_to_obj函数不是太慢的话,它可能比嵌套生成器表达式快)。

zqry0prt

zqry0prt6#

列表解析对于简单的情况来说是很好的,但是有时候简单的for循环是最简单的解决方案:

other_list = []
for v in v_list:
    obj = map_to_obj(v)
    if obj:
        other_list.append(obj)

现在,如果你真的想要一个列表组件,而不想构建一个临时列表,你可以使用filtermap的迭代器版本:

import itertools as it
result = list(it.ifilter(None, it.imap(map_to_obj, v_list)))

或者更简单地说:

import itertools as it
result = filter(None, it.imap(map_to_obj, v_list)))

迭代器版本不构建临时列表,它们使用惰性求值。

ljsrvy3e

ljsrvy3e7#

我已经找到了使用reduce的方法:

def map_and_append(lst, v):
    mapped = map_to_obj(v)
    if mapped is not None:
        lst.append(mapped)
    return lst

reduce(map_and_append, v_list, [])

这个的性能怎么样?

2vuwiymt

2vuwiymt8#

我发现的最好的方法是这样的,它是神秘的,但简洁:

[f(y) for x in some_list()
      for y in [some_item(x)]  # wastefully making a singleton list
      if some_condition(y)]

相关问题