Reputation: 3495
If I have 2 or 3 of the same calculations done within a generator for each loop, is there a way to just set them as a variable?
A quick example would be like this:
#Normal
[len( i ) for i in list if len( i ) > 1]
#Set variable
[x for i in list if x > 1; x = len( i )]
Before anyone says len( i )
would be so fast the difference would be negligible, I also mean for other calculations, using len just made it easier to read.
Also, if there is a way, how would you set multiple variables?
Apologies if it's been asked before, but I've searched around and not found anything.
Upvotes: 1
Views: 2217
Reputation: 180401
using itertools.imap
in python2 will be an efficient way to do what you need and most likely outperform a generator expression:
[x for x in imap(len, lst) if x > 4]
Upvotes: 1
Reputation: 13171
Most implementations of Python do not, as you correctly surmise, have common sub-expression optimization, so your first expression would indeed call len(x) twice per iteration. So why not just have two comprehensions:
a = [len(x) for x in list]
b = [x for x in a if x > 1]
That make two passes, but only one call of len() per. If the function were an expensive one, that's probably a win. I'd have to time this to be sure.
Cyber's nested version is essentially the same thing.
Upvotes: 3
Reputation: 117856
One way to get around the expensive operation is to nest a generator in a list comprehension that simply acts as a filter, for example
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]
Using analogous functions and variables to your example, you'd have
[x for x in (len(i) for i in list) if x > 1]
Upvotes: 8