在python列表理解中设置变量

在python列表理解中设置变量,python,generator,Python,Generator,如果我在一个生成器中为每个循环进行了2或3次相同的计算,有没有办法将它们设置为变量 一个简单的例子如下: #Normal [len( i ) for i in list if len( i ) > 1] #Set variable [x for i in list if x > 1; x = len( i )] 在任何人说len(i)速度如此之快,差异可以忽略不计之前,我的意思是,对于其他计算,使用len只是让它更容易阅读。 另外,如果有办法,您将如何设置多个变量 如果以前有人问

如果我在一个生成器中为每个循环进行了2或3次相同的计算,有没有办法将它们设置为变量

一个简单的例子如下:

#Normal
[len( i ) for i in list if len( i ) > 1]

#Set variable
[x for i in list if x > 1; x = len( i )]
在任何人说len(i)速度如此之快,差异可以忽略不计之前,我的意思是,对于其他计算,使用len只是让它更容易阅读。 另外,如果有办法,您将如何设置多个变量


如果以前有人问过,我会向您道歉,但我已经到处搜索了,没有找到任何东西。

解决这个昂贵操作的一种方法是在列表理解中嵌套一个生成器,例如,它只是一个过滤器

def foo(x):       # assume this function is expensive
    return 2*x

>>> [j for j in (foo(i) for i in range(6)) if j > 4]
#                ^ only called once per element
[6, 8, 10]
在示例中使用类似的函数和变量

[x for x in (len(i) for i in list) if x > 1]

一种绕过昂贵操作的方法是在列表理解中嵌套一个生成器,例如,它只是作为一个过滤器

def foo(x):       # assume this function is expensive
    return 2*x

>>> [j for j in (foo(i) for i in range(6)) if j > 4]
#                ^ only called once per element
[6, 8, 10]
在示例中使用类似的函数和变量

[x for x in (len(i) for i in list) if x > 1]

在python2中使用
itertools.imap
将是一种有效的方法,可以满足您的需要,并且很可能优于生成器表达式:

[x for x in  imap(len, lst) if x > 4]

在python2中使用
itertools.imap
将是一种有效的方法,可以满足您的需要,并且很可能优于生成器表达式:

[x for x in  imap(len, lst) if x > 4]

正如您正确推测的那样,大多数Python实现没有公共子表达式优化,因此您的第一个表达式确实会在每次迭代中调用len(x)两次。那么,为什么不能有两种理解:

a = [len(x) for x in list]
b = [x for x in a if x > 1]
这会进行两次传递,但每次只调用一次len()。如果功能是昂贵的,那可能是一个胜利。我得确定一下时间


Cyber的嵌套版本本质上是一样的。

大多数Python实现没有,正如您正确猜测的那样,具有公共子表达式优化,因此您的第一个表达式确实会在每次迭代中调用len(x)两次。那么,为什么不能有两种理解:

a = [len(x) for x in list]
b = [x for x in a if x > 1]
这会进行两次传递,但每次只调用一次len()。如果功能是昂贵的,那可能是一个胜利。我得确定一下时间



Cyber的嵌套版本本质上是一样的。

ah谢谢,这种方式很有意义,当然,将
(foo(i)for i in range(6))
也移出会更好。你不能移出这个表达式,在你的例子中,这就是对所有
i
调用
len
。外部列表理解为每个元素获取
len
的输出,然后将其与您的标准进行比较。将列表理解和生成器混合在一起有什么好处吗?(比如“嵌套列表理解”/“嵌套生成器”)@SylvainLeroux是的,生成器将只生成从外部列表理解逐个调用的元素。嵌套列表理解将一次创建一个列表,然后执行外部列表理解。对不起,我没有正确地阅读它,误解了代码啊哈,是的,我现在完全明白了,谢谢:)啊,谢谢,这种方式很有意义,当然,尽管将
(foo(I)for I移到范围(6))会更好
也移出它吗?您不能将该表达式移出,这就是在您的示例中对所有
i
调用的
len
。外部列表理解为每个元素获取
len
的输出,然后将其与您的标准进行比较。将列表理解和生成器混合在一起有什么好处吗?(比如“嵌套列表理解”/“嵌套生成器”)@SylvainLeroux是的,生成器将只生成从外部列表理解逐个调用的元素。嵌套列表理解将一次创建一个列表,然后执行外部列表理解。对不起,我没有正确阅读它,误解了代码啊哈,是的,我现在完全明白了,谢谢:)因为我的理解到目前为止,OP基本上是试图在表达式
[func(x)>中x的func(x)如果func(x)>某物]
的每次迭代中将
func
调用从2减少到1。对于每个这样的
func
调用,计算
func
的代价可能会有很大的不同。常见的子表达式也是一个潜在的错误源,这也是一个麻烦的语法。我经常想过滤输出,而不是输入,而公共子表达式的显式简洁语法会让事情变得更清楚。问题的一部分?我们如何在客观上比嵌套理解更好的语法上达成一致?据我所知,OP基本上是在表达式
[func(x)for x in list if func(x)>something]的每次迭代中将
func
调用从2减少到1。对于每个这样的
func
调用,计算
func
的代价可能会有很大的不同。常见的子表达式也是一个潜在的错误源,这也是一个麻烦的语法。我经常想过滤输出,而不是输入,而公共子表达式的显式简洁语法会让事情变得更清楚。问题的一部分?我们如何在客观上比嵌套理解更好的语法上达成一致?“大多数Python实现没有,正如您正确猜测的那样,具有公共子表达式优化”。事实上,公共子表达式优化似乎没有在特定情况下执行(至少在CPython 3.3.0中)。给定OP数据(内联代码很抱歉):
>>def l(i):。。。全球a。。。a+=1。。。返回len(i)…>>>a=0>>>[l(i)表示i,如果l(i)>1][2,2,3]>>>a 7,如您所见,my
l
函数在4元素列表中被调用7次。具有副作用的函数在任何情况下都不符合通用子表达式优化的条件。如果它们不属于同一个模块,优化器是否能够区分具有副作用的函数?一个好的C编译器会发现这种情况。Python肯定是ab