Why i for i?


Why is it:

evens_to_50 = [i for i in range(51) if i % 2 == 0]
print evens_to_50

rather than just:

evens_to_50 = [i in range(51) if i % 2 == 0]
print evens_to_50


i is the value being appended to the list if it is even. It is refreshed with each iteration of the loop.

List comprehensions do not have a built in iterator, and need a loop construct to work. i in range(51) is a boolean expression, not a loop.

>>> i in range(51)
Traceback (most recent call last):
  File "<pyshell#62>", line 1, in <module>
    i in range(51)
NameError: name 'i' is not defined
>>> i = 50
>>> i in range(51)
>>> i = 51
>>> i in range(51)

We need something to give i a value from within the range.


After digging around I cannot find any example of a list comprehension that does not use for x in n though I suspect there is no limiting what n is so long as it’s iterable, another list (or dict) comprehension, a range, filter or map object and probably even a generator. It would be funny to use a filter object given that comprehensions don’t just assign a function to the list, they filter them too, like you have above. Bottom line, for x in n is the engine.


The following, from Python: 5. Data Structures 5.1.3. List Comprehensions, is consistent with what @mtf has stated above regarding the necessity of including at least one for in the list comprehension …

A list comprehension consists of brackets containing an expression followed by a for clause, then zero or more for or if clauses. The result will be a new list resulting from evaluating the expression in the context of the for and if clauses which follow it.


Some silliness…

>>> n = list('abcdefghijklmnopqrstuvwxyz')
>>> b  = [n.pop() for x in n]
>>> b
['z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n']
>>> n
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm']
>>> b  = [(n.pop(), n.pop()) for x in n for y in n]
>>> b
[('m', 'l'), ('k', 'j'), ('i', 'h'), ('g', 'f'), ('e', 'd'), ('c', 'b')]
>>> n



Very interesting example, @mtf, of some effects of modifying an iterable object as it is traversed.

That and the example below it illustrate that the expression preceding the for is not restricted to being the variable that is between for and the in. The latter (the variable) represents each item in the iterable object during the loop, while the prior (the expression) is evaluated during each iteration to determine what value will be placed in the list during that iteration, subject to evaluation of if clauses, if present. In fact, the expression to be evaluated does not need to make any use of the variable at all.


There’s both assignment and the use of the assigned variable. If you were to skip one the other doesn’t make sense, and neither can be automatically done since then it’s not possible to tell whether you meant some outside variable. There may also be multiple variables being assigned to:

[a+b for (a, b) in [[1, 2]]]  # [3]

>>> letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
>>> def unique_english_letters(word):
	return len({x for x in word if x in letters})

>>> unique_english_letters('Mississippi')

Set comprehension cannot be left out of the discussion.


This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.