首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否可以从Python列表理解中捕获返回值以使用条件?

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

Stack Overflow用户
提问于 2012-01-07 00:57:40
回答 4查看 1.3K关注 0票数 7

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

代码语言:javascript
运行
复制
[expensive_function(x) for x in generator where expensive_function(x) < 5]

我想避免每次迭代调用两次expensive_function

generator可能会返回一个无限系列,并且列表理解不会被懒惰地计算。所以这是行不通的:

代码语言:javascript
运行
复制
[y in [expensive_function(x) for x in generator where expensive_function(x)] where y < 5]

我可以用另一种方式来写,但这对于列表理解来说是正确的,而且我确信这是一种常见的使用模式(无论可能与否!)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-01-07 01:05:20

如果generator可能是无限的,那么您不希望使用列表理解。而且,并不是所有的东西都必须是一行。

代码语言:javascript
运行
复制
def filtered_gen(gen):
    for item in gen:
        result = expensive_function(item)
        if result < 5:
            yield result
票数 10
EN

Stack Overflow用户

发布于 2012-03-27 08:04:44

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

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

代码语言:javascript
运行
复制
[expensive_function(x) for x in xrange(5) if expensive_function(x) % 2 == 0]

expensive_function通过您的过滤器时,您希望避免计算两次。具有更具表现力的理解语法的语言(Scala、Haskell等)允许您简单地为通过理解变量计算的表达式指定名称,这使您可以执行以下操作:

代码语言:javascript
运行
复制
# NOT REAL PYTHON
[result for x in xrange(5) for result = expensive_function(x) if result % 2 == 0]

但是,通过将赋值result = expensive_function(x)转换为一个元素序列上的另一个for迭代,可以很容易地模拟这一点:

代码语言:javascript
运行
复制
[result for x in xrange(5) for result in (expensive_function(x),) if result % 2 == 0]

证据是:

代码语言:javascript
运行
复制
>>> 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]
票数 3
EN

Stack Overflow用户

发布于 2012-01-07 01:13:58

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

代码语言:javascript
运行
复制
ys_all = (expensive(x) for x in xs)
ys_filtered = (y for y in ys_all if y <5)

代码语言:javascript
运行
复制
from itertools import imap, ifilter
ys = ifilter(lambda y : y < 5, imap(expensive, xs))
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8761437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档