[英]Python list comprehension with same function in guard and result
I was wondering if someone has a nice clean Pythonic and effective technique for implementing comprehensions that involve the same expression in the guard as in the result. 我想知道是否有人有一个很好的干净Pythonic和有效的技术来实现在结果中涉及保护中相同表达的理解。 To be clear, consider the following simple example: 需要说明的是,请考虑以下简单示例:
def f(a):
print "Calling", a
return a + 1
print [ f(v) for v in xrange(3) if f(v) > 1 ]
This will print 这将打印
Calling 0
Calling 1
Calling 1
Calling 2
Calling 2
[2, 3]
proving that f is called twice for most elements. 证明f对于大多数元素被调用两次。 This is fine and what we want if f has side-effects, but if f is some expensive operation without side-effects, the duplicate call is not desirable. 这很好,如果f有副作用,我们想要什么,但如果f是一些没有副作用的昂贵操作,重复调用是不可取的。 But the solution that only calls f once for each element seems clumsy/verbose to me: 但是对于每个元素只调用f一次的解决方案对我来说似乎笨拙/冗长:
intermediate = ( f(v) for v in xrange(3) )
print [ r for r in intermediate if r > 1 ]
even if it is contracted into one line 即使它被收缩成一条线
print [ r for r in ( f(v) for v in xrange(3) ) if r > 1 ]
So, can anyone come up with something better? 那么,任何人都能想出更好的东西吗?
You can use the filter()
function: 您可以使用filter()
函数:
filter(lambda x: x > 1, [ f(v) for v in xrange(3)])
But that's about as verbose as your last suggested solution. 但这与您上次建议的解决方案一样冗长。
How about memoizing f
, eg:? 如何记忆f
,例如:?
def f(...): ...
def some_or_other():
f = functools.lru_cache(1)(f)
[ f(v) for v in xrange(3) if f(v) > 1 ]
Memoizing locally, withing the scope of your call site has the advantage that once some_or_other()
returns, "memo" memory will be garbage collected, and you don't have to worry about references to v
that were passed to f()
. 在本地进行记忆,具有调用站点的范围具有以下优点:一旦some_or_other()
返回,“memo”内存将被垃圾收集,并且您不必担心传递给f()
对v
引用。
Since it's local, memo size limit 1 is sufficient. 由于它是本地的,备忘录大小限制1就足够了。
In the simple case, you can also memoize f
globally: 在简单的情况下,您还可以全局记忆f
:
@functools.lru_cache()
def f(...): ...
[ f(v) for v in xrange(3) if f(v) > 1 ]
What Andrés Pérez-Albela H. said, except use map() built-in function: 什么AndrésPérez-Albela H.说,除了使用map()内置函数:
filter(lambda x: x > 1, map(f, xrange(3)))
You could also look at itertools module, but I'm not sure if it can be applied to this example. 您还可以查看itertools模块,但我不确定它是否可以应用于此示例。 In more complex situations though it may offer a solution. 在更复杂的情况下,它可能提供解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.