Peter
Peter

Reputation: 3495

Set variables in python list comprehension

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

Answers (3)

Padraic Cunningham
Padraic Cunningham

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

Lee Daniel Crocker
Lee Daniel Crocker

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

Cory Kramer
Cory Kramer

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

Related Questions