When reading the official tutorial, I encountered this example:
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
I couldn't understand this, so I did some experiments:
>>> [num for elem in vec]
[9, 9, 9]
>>> [num for elem in (vec for num in elem)]
[9, 9, 9]
And I'm even more confused now!
In which order should I read a list comprehension?
I'm sure I haven't defined a num
variable with the value 9 anywhere.
python
Output:
Python 2.7.10 (default, Oct 23 2015, 19:19:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
REPL session:
>>> num
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'num' is not defined
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [num for elem in vec]
[9, 9, 9]
>>> [num for elem in (vec for num in elem)]
[9, 9, 9]
The loops in list comprehension are read from left to right. If your list comprehension would be written as an ordinary loop, it would look something like this:
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> l = []
>>> for elem in vec:
... for num in elem:
... l.append(num)
...
>>> l
[1, 2, 3, 4, 5, 6, 7, 8, 9]
In Python 2, the variables within the list comprehension share the outer scope, so num
is available to be used later:
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> num
9
Note that on Python 3, the behavior is different:
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> num
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'num' is not defined