2016-07-16 57 views
0

当读official tutorial,我遇到了这个例子:了解列表综合Python中

>>> 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] 

而且我甚至现在更困惑了!

所以,我的问题是:我应该以哪种顺序阅读列表理解?


编辑:我敢肯定,我还没有和值9任何位置定义的变量num

sunqingyaos-MacBook-Air:Documents sunqingyao$ 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. 
>>> 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] 
>>> 
+0

我也很困惑。 '[num for elem in vec]'应该抛出一个错误,因为'num'没有被定义。你确定你还没有在某个地方定义一个带有“9”值的'num'变量吗? –

+0

@Rawing是的,我确定。看到我更新的问题 –

回答

4

列表理解的循环读取由左到右。如果您的列表理解将被写为普通循环会是这个样子:

>>> 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] 

在Python 2列表解析份额内的变量外范围,使num可以供以后使用:

>>> 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 

需要注意的是关于Python 3的行为是不同的:

>>> 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 
2

不用担心:)。

当您执行列表理解时,num的值为9,所以下一次迭代vec时。你会得到一个9的清单。

看到这个。

In [1]: vec = [[1,2,3], [4,5,6], [7,8,9]] 
In [2]: [num for elem in vec for num in elem] 
Out[2]: [1, 2, 3, 4, 5, 6, 7, 8, 9] 
In [3]: num 
Out[3]: 9 
In [4]: [num for elem in vec] 
Out[4]: [9, 9, 9] 
+0

所以这实际上是一个错误? http://sackoverflow.com/a/4199355/5399734 –

+0

@sunqingyao很好。谢谢你指出,作为一个错误。 –

+1

@sunqingyao不,这不是一个错误,在较旧版本的Python中列表解析运行在周围代码的范围内。出于效率原因,故意这样做。但是很多人抱怨说它已经改为Python 3.这意味着Python 3列表组件不会“泄漏”,但它们也比Python 2列表组件更慢,并且会消耗更多的RAM。 –

0
list1 = [num for elem in vec for num in elem] 

#is equivalent to: 

list1 = [] 
for elem in vec: 
    for num in elem: 
     list1.append(num) 
+0

其实OP有下一行的问题。不是这个。 –

0

让我尽量让答案更清零。 而且顺序显然是从左到右,最右边的值将被存储在变量num和elem中。

初始化数据:

vec = [[1,2,3], [4,5,6], [7,8,9]] 
num # Undefined 
elem # Undefined 

步骤-1:线执行后[num for elem in vec for num in elem]

# Now the value of undefined variable will be 
num = 9 # will keep the last value of the loop as per python 2.7 
elem = [7, 8, 9] # Same applies here (as the loop for elem in vec will get executed first followed by for num in elem) 

步骤2:行执行后[num for elem in vec]

# Output: [9, 9, 9] 
# Since num value is 9 and its get repeated 3 times because of vec has 3 elements (three list object in a list, so for loop will run 3 times) 
# Now the variable value would be 
num = 9 # no change 
elem = [7, 8, 9] # The last tuple of variable vec 

步骤3:执行后[num for elem in (vec for num in elem)]

1. In the first/right loop i.e (vec for num in elem) 
    Here the result will be a generator that will have run thrice since length of elem is 3. 
2. Final for loop will iterate over RESULT1 (the result of for loop #1 having length 3) and since the num value is 9. the result will be [9, 9, 9] # num value repeated thrice.