这个例子:
>>> 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]
现在我更加困惑了!
我应该按照什么顺序阅读列表推导?
我确定我没有num在任何地方定义值为 9 的变量。
num
python
输出:
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会话:
>>> 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 confusion you’re experiencing comes from how list comprehensions work, especially with nested ones. Let’s go through each case to clarify the behavior:
vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] [num for elem in vec for num in elem]
This list comprehension flattens the nested list. Here’s how it works: - for elem in vec: Iterates through each sublist (like [1, 2, 3]). - for num in elem: For each elem, it iterates through its elements (like 1, 2, 3). - This results in a flattened list where all the numbers are collected: [1, 2, 3, 4, 5, 6, 7, 8, 9].
for elem in vec
[1, 2, 3]
for num in elem
elem
1, 2, 3
[1, 2, 3, 4, 5, 6, 7, 8, 9]
So, the order of the loops is important, and the comprehension works from left to right—first iterating over the outer list (vec), and then over each inner list (elem).
vec
[num for elem in vec]
Here, you’re only iterating over vec, but you haven’t specified what to extract from each elem. Since you’re not doing anything with elem, this doesn’t work as expected. In fact, Python will just use elem as is, so it defaults to using the last element of vec for num. Since vec ends with [7, 8, 9], that’s what is returned:
[7, 8, 9]
[9, 9, 9]
This happens because Python is just placing the value of elem in num for each iteration, which happens to be the last element of the outer list, [7, 8, 9].
[num for elem in (vec for num in elem)]
This is even more confusing. The expression (vec for num in elem) is a generator expression that does not make sense here. Essentially, it just generates vec over and over again without any useful transformation. Because of this, the result will again be just the last item of vec, which is [7, 8, 9], and Python places num as the last element of each iteration, resulting in [9, 9, 9].
(vec for num in elem)
List comprehensions are evaluated from left to right: 1. The first for iterates through the outer list (in your case, vec). 2. The second for iterates through each sublist (in your case, the elements inside each sublist).
for
So, for example, the correct list comprehension to flatten vec would be:
[num for elem in vec for num in elem]
This iterates through each sublist (elem) inside vec, and for each elem, it iterates through each number (num).
Let me know if you’d like further clarification on how list comprehensions work!