是否可以从Python列表中捕获返回值以使用条件?

是否可以从Python列表中捕获返回值以使用条件?,python,list-comprehension,Python,List Comprehension,我想在列表中构造一个值,但也要过滤该值。例如: [expensive_function(x) for x in generator where expensive_function(x) < 5] 我可以用另一种方式写这篇文章,但它适合列表理解,我确信这是一种常见的使用模式(可能或不可能!)。如果生成器可能是无限的,您不想使用列表理解。并不是每件事都必须是一行 def filtered_gen(gen): for item in gen: result = exp

我想在列表中构造一个值,但也要过滤该值。例如:

[expensive_function(x) for x in generator where expensive_function(x) < 5]

我可以用另一种方式写这篇文章,但它适合列表理解,我确信这是一种常见的使用模式(可能或不可能!)。

如果
生成器可能是无限的,您不想使用列表理解。并不是每件事都必须是一行

def filtered_gen(gen):
    for item in gen:
        result = expensive_function(item)
        if result < 5:
            yield result
def已过滤_gen(gen):
对于gen中的项目:
结果=昂贵的功能(项目)
如果结果<5:
产量结果

您应该创建两个生成器表达式:

ys_all = (expensive(x) for x in xs)
ys_filtered = (y for y in ys_all if y <5)
ys_all=(x中x的昂贵(x))

ys_filtered=(y代表y在ys_all if y y警告这有点复杂,但确实起作用。我将用一个例子来解释它

比如说
昂贵的函数=math.sin

infinite generator=collections.count(0.1,0.1)

然后

所以你的问题归结为

[z for z in (y if y < 0.5 else next(iter([])) \
         for y in (expensive_function(x) for x in generator))]

顺便说一句:
sin
在真正意义上在整个范围内是非单调的
(0,2pi)

我将回答问题的一部分,关于如何在列表理解中捕获中间结果以用于条件,而忽略从无限生成器构建的列表理解的问题(这显然是行不通的),以防有人来这里寻找标题中问题的答案

所以,你有这样一个列表理解:

[expensive_function(x) for x in xrange(5) if expensive_function(x) % 2 == 0]
当函数通过过滤器时,您希望避免计算两次
昂贵的函数
。使用更具表达性的理解语法(Scala、Haskell等)的语言,您可以简单地为从理解变量计算的表达式指定名称,这使您可以执行以下操作:

# NOT REAL PYTHON
[result for x in xrange(5) for result = expensive_function(x) if result % 2 == 0]
但是,您可以通过将赋值
result=expensive_函数(x)
转换为另一个
,以便在一个元素序列上进行迭代来轻松模拟:

[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]

item
的最后两次出现是否应该替换为
result
?+1。您可以使用itertools和生成器表达式,但这更容易理解。不,如果
xs
是无限的,就不会了。遗憾的是,Python没有Haskell列表理解。在某个地方,某些东西会爆炸。是的!这是最好的答案在我看来!你能称它们为“生成器理解”而不是列表理解吗?疯狂!这是微妙的不同,因为
sin
是一个非单调函数(我没有说
昂贵的函数
是单调的,但它是!)这会在第一次条件为非真时停止,不会在条件为真的所有条件下继续。也就是说,如果它是非单调的,这将导致一个无限的计算…@Joe,这甚至适用于非单调函数。请参阅我的更新。有任何值得接受的答案吗?如果没有,有什么信息你还在找吗?很抱歉忘了标记这个。谢谢你的回答!没问题。希望你只是需要一个提醒。:)
[z for z in (y if y < 7 else next(iter([])) for y in 
      (random.randint(1,10)*x for x in itertools.count(0.1,0.1)))]

[0.9,
 0.6000000000000001,
 1.8000000000000003,
 4.0,
 0.5,
 6.0,
 4.8999999999999995,
 3.1999999999999997,
 3.5999999999999996,
 5.999999999999999]
[expensive_function(x) for x in xrange(5) if expensive_function(x) % 2 == 0]
# NOT REAL PYTHON
[result for x in xrange(5) for result = expensive_function(x) if result % 2 == 0]
[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]