Python列表理解在guard和result中具有相同的功能

时间:2015-12-02 07:48:38

标签: python python-2.7 list-comprehension

我想知道是否有人有一个很好的干净的Pythonic和有效的技术来实现在结果中涉及保护中相同表达的理解。 需要明确的是,请考虑以下简单示例:

config.htmlEncodeOutput = false;
config.entities = false;

这将打印

def f(a):
    print "Calling", a
    return a + 1

print [ f(v) for v in xrange(3) if f(v) > 1 ]

证明大多数元素都会调用f两次。这很好,如果f有副作用,我们想要什么,但如果f是一些没有副作用的昂贵操作,重复调用是不可取的。但是对于每个元素只调用f一次的解决方案对我来说似乎笨拙/冗长:

Calling 0
Calling 1
Calling 1
Calling 2
Calling 2
[2, 3]

即使它被缩减为一行

intermediate = ( f(v) for v in xrange(3) ) 
print [ r for r in intermediate if r > 1 ]

那么,任何人都能想出更好的东西吗?

3 个答案:

答案 0 :(得分:2)

您可以使用 filter() 功能:

filter(lambda x: x > 1, [ f(v) for v in xrange(3)])

但这与你上一次建议的解决方案一样冗长。

答案 1 :(得分:1)

如何记忆f,例如:?

def f(...): ...

def some_or_other():
    f = functools.lru_cache(1)(f)
    [ f(v) for v in xrange(3) if f(v) > 1 ]

在本地进行记事,使用您的呼叫站点的范围具有以下优点:一旦some_or_other()返回,“备忘录”内存将被垃圾收集,您不必担心对v的引用已传递给f()

由于它是本地的,备忘录大小限制1就足够了。

在简单的情况下,您还可以全局地记住f

@functools.lru_cache()
def f(...): ...

[ f(v) for v in xrange(3) if f(v) > 1 ]

答案 2 :(得分:0)

AndrésPérez-Albela H.说,除了使用map()内置函数外:

filter(lambda x: x > 1, map(f, xrange(3)))

您还可以查看itertools模块,但我不确定它是否可以应用于此示例。在更复杂的情况下,它可能提供解决方案。