我想在列表理解中构造一个值,但也要对该值进行过滤。例如:
[expensive_function(x) for x in generator where expensive_function(x) < 5]我想避免每次迭代调用两次expensive_function。
generator可能会返回一个无限系列,并且列表理解不会被懒惰地计算。所以这是行不通的:
[y in [expensive_function(x) for x in generator where expensive_function(x)] where y < 5]我可以用另一种方式来写,但这对于列表理解来说是正确的,而且我确信这是一种常见的使用模式(无论可能与否!)。
发布于 2012-01-07 01:05:20
如果generator可能是无限的,那么您不希望使用列表理解。而且,并不是所有的东西都必须是一行。
def filtered_gen(gen):
for item in gen:
result = expensive_function(item)
if result < 5:
yield result发布于 2012-03-27 08:04:44
我将回答问题中关于如何在条件中使用的列表理解中捕获中间结果的部分,并忽略从无限生成器构建的列表理解的问题(这显然是行不通的),以防有人在这里寻找标题中问题的答案。
所以,你有一个这样的列表理解:
[expensive_function(x) for x in xrange(5) if expensive_function(x) % 2 == 0]当expensive_function通过您的过滤器时,您希望避免计算两次。具有更具表现力的理解语法的语言(Scala、Haskell等)允许您简单地为通过理解变量计算的表达式指定名称,这使您可以执行以下操作:
# NOT REAL PYTHON
[result for x in xrange(5) for result = expensive_function(x) if result % 2 == 0]但是,通过将赋值result = expensive_function(x)转换为一个元素序列上的另一个for迭代,可以很容易地模拟这一点:
[result for x in xrange(5) for result in (expensive_function(x),) if result % 2 == 0]证据是:
>>> def expensive_function(x):
print 'expensive_function({})'.format(x)
return x + 10
>>> [expensive_function(x) for x in xrange(5) if expensive_function(x) % 2 == 0]
expensive_function(0)
expensive_function(0)
expensive_function(1)
expensive_function(2)
expensive_function(2)
expensive_function(3)
expensive_function(4)
expensive_function(4)
[10, 12, 14]
>>> [result for x in xrange(5) for result in (expensive_function(x),) if result % 2 == 0]
expensive_function(0)
expensive_function(1)
expensive_function(2)
expensive_function(3)
expensive_function(4)
[10, 12, 14]发布于 2012-01-07 01:13:58
你应该创建两个生成器表达式:
ys_all = (expensive(x) for x in xs)
ys_filtered = (y for y in ys_all if y <5)或
from itertools import imap, ifilter
ys = ifilter(lambda y : y < 5, imap(expensive, xs))https://stackoverflow.com/questions/8761437
复制相似问题