如何在不重复评估函数的情况下编写列表推导?

时间:2016-10-31 22:15:05

标签: python list-comprehension

我为这个微不足道的问题道歉,但我找不到解决方案。我需要创建以下列表:

for i in x:
    if(f(i) < g(i)):
         my_list.append(f(i)*g(i))

但我不知道如何使用列表理解来完成,而不重复计算函数f()g()。我想避免它,因为它们的计算成本很高。所以我不想要这样的东西:

[f(i)*g(i) for i in x if f(i) < g(i)]

因为f(i)g(i)在每次迭代时都会计算两次。我想知道是否有办法存储&#34;数字f(i)g(i)的某处,并在列表理解中回忆它们。

4 个答案:

答案 0 :(得分:3)

如果您创建一个只有一个元素的可迭代(如元组或列表),您可以将调用值存储在for循环目标中;一个元素将是(f(i), g(i))结果的元组:

res = [fi * gi for i in x for fi, gi in [(f(i), g(i))] if fi < gi]

然而,这是不太漂亮而且不太可读。

使用实际的for循环会好得多:

res = []
for i in x:
    fi, gi = f(i), g(i)
    if fi < gi:
        res.append(fi * gi)

另一种选择是生成一个计算f(i)g(i)的中间生成器表达式,然后在列表推导中使用输出:

intermediate = ((f(i), g(i)) for i in x)
res = [fi * gi for fi, gi in intermediate if fi < gi]

答案 1 :(得分:1)

嗯...非常基础......用于存储g(i)f(i)结果的变量怎么样?

而不是

for i in x:
    if(f(i) < g(i)):
         my_list.append(f(i)*g(i))

做类似

的事情
for i in x:
    a = f(i)
    b = g(i)
    if a < b:
         my_list.append(a*b)

答案 2 :(得分:1)

您可以避免使用append,如下所示:

def func(x):
    for i in x:
        a = f(i)
        b = g(i)
        if a < b:
            yield a*b

my_list = list(func(x))

答案 3 :(得分:1)

考虑

[ fi * gi for fi, gi in zip(map(f, x), map(g, x)) if fi < gi ]