How to Do Assignments in a List Comprehension

How can I use assignment operation in list comprehension in python and convert following iterative code into it?

For starters, you shouldn't be using list comprehensions for side-effects. List comprehensions are for expressing functional, mapping/filtering operations on arbitrary iterables to create a new list.

Furthermore, assignment expressions explicitly aren't allowed to be used for item-assignment (a[k] = b), only simple assignment to a name (a = b). So you could just use a function to use the assignment statement:

In [1]: def _reverse_helper(word, i):
...: length = len(word)
...: word[i] , word[(length-1)-i] = word[(length-1)-i] , word[i]
...:

In [2]: word = list("overflow")
...:

Now, it doesn't make any sense to re-assign the result of your list comprehension to word again, because you are using the list comprehension for side-effects. So, doing something like this is the closest equivalent to your original implementation:

In [3]: [_reverse_helper(word, i) for i in range(len(word)//2)]
Out[3]: [None, None, None, None]

In [4]: word
Out[4]: ['w', 'o', 'l', 'f', 'r', 'e', 'v', 'o']

List comprehension with assignments

Assignments are statements, which are not allowed in list comprehensions, which support only expressions.

You can use sum instead:

sources = {index: sum(1 for index in range(len(source)) if source == sources[index]) for source in data['Source']}

A more efficient method would be to use collections.Counter, as @Amadan has suggested in the comments:

import collections.Counter:
sources = Counter(index for source in data['Source'] for index in range(len(source)) if source == sources[index])

How to set local variable in list comprehension?

Starting in Python 3.8, and the introduction of assignment expressions (PEP 572) (:= operator), it's possible to use a local variable within a list comprehension in order to avoid calling the same function twice.

In our case, we can name the evaluation of map_to_obj(v) as a variable o while using the result of the expression to filter the list; and thus use o as the mapped value:

[o for v in [v1, v2, v3, v4] if (o := map_to_obj(v))]

Two assignments in single python list comprehension

When in doubt about efficiency use the timeit module, it's always easy to use:

import timeit

def f1(aRange):
x = [2*i for i in aRange]
y = [3*i for i in aRange]
return x,y

def f2(aRange):
x, y = zip(*[(2*i, 3*i) for i in aRange])
return x,y

def f3(aRange):
x, y = zip(*((2*i, 3*i) for i in aRange))
return x,y

def f4(aRange):
x = []
y = []
for i in aRange:
x.append(i*2)
y.append(i*3)
return x,y

print "f1: %f" %timeit.Timer("f1(range(100))", "from __main__ import f1").timeit(100000)
print "f2: %f" %timeit.Timer("f2(range(100))", "from __main__ import f2").timeit(100000)
print "f3: %f" %timeit.Timer("f3(range(100))", "from __main__ import f3").timeit(100000)
print "f4: %f" %timeit.Timer("f4(range(100))", "from __main__ import f4").timeit(100000)

The results seem to be consistent in pointing to the first option as the quickest.

f1: 2.127573
f2: 3.551838
f3: 3.859768
f4: 4.282406

list comprehension with multiple assignments

List comprehensions are great, but sometimes they're not best the solution, depending on requirements for readability and speed. Sometimes, just writing out the implied for loop (and if statement) is more readable and quicker.

def factors(n):
l = []
for i in range(1, int(n**0.5)+1):
if n % i == 0:
l.append(i)
l.append(n//i)
return l

For small numbers, the above function is quicker than the list comprehension. At larger numbers (1,000,000 and bigger), the function and list comprehension are equal in terms of speed.

For a slight speed increase you can also cache the append method of the list, though this makes the function slightly less readable.

def factors(n):
l = []
append = l.append
for i in range(1, int(n**0.5)+1):
if n % i == 0:
append(i)
append(n//i)
return l

Speed comparison:

In [86]: %timeit factors_list_comprehension(1000)
100000 loops, best of 3: 7.57 µs per loop

In [87]: %timeit factors_function(1000)
100000 loops, best of 3: 6.24 µs per loop

In [88]: %timeit factors_optimised_function(1000)
100000 loops, best of 3: 5.81 µs per loop

In [89]: %timeit factors_list_comprehension(1000000)
10000 loops, best of 3: 111 µs per loop

In [90]: %timeit factors_function(1000000)
10000 loops, best of 3: 108 µs per loop

In [91]: %timeit factors_optimised_function(1000000)
10000 loops, best of 3: 106 µs per loop

Can assignments be made as part of python list comprehension?

All you need to do is:

shod_l = [pd.DataFrame() for _ in shod_list]

or if using a variable q:

shod_l = [pd.DataFrame() for q in shod_list]

or if you're determined to use a range:

shod_l = [pd.DataFrame() for q in range(len(shod_list))]


Related Topics



Leave a reply



Submit