列表理解中for语句的顺序 [英] Order of for statements in a list comprehension
问题描述
在python2.7中,我试图在字符串列表中的每个项目之前加上另一个项目(例如,在列表['b','c']中的每个项目之前添加项目'a').通过如何在列表理解中添加列表列表,我确定了正确的命令,其归结为:
In python2.7, I am trying to prepend every item in a list of strings with another item (eg. add item 'a' before every item in the list ['b', 'c']). From How to add list of lists in a list comprehension, I have determined the correct command, which boils down to:
>>> [i for x in ['b', 'c'] for i in ['a', x]]
['a', 'b', 'a', 'c']
纯粹基于临时i和x变量,以下版本似乎更具可读性.但是,它给出了完全不同的结果.为什么这不会给出相同的结果?
Based purely on the temporary i and x variables, the version below seems more readable. However, it gives a completely different result. Why does this not give the same result?
>>> [i for i in ['a', x] for x in ['b', 'c']]
['a', 'a', 'c', 'c']
更奇怪的是,"b"条目发生了什么?
Even more curious, what happened to the 'b' entry?
推荐答案
列表理解中的for
循环始终按嵌套顺序列出.您可以使用相同的嵌套顺序将这两个理解写成常规循环.请记住,只有第一个for
之前的表达式会产生最终值,因此请将其放入循环中.
The for
loops in list comprehensions are always listed in nesting order. You can write out both of your comprehensions as regular loops using the same order to nest; remember that only the expression before the first for
produces the final values, so put that inside the loops.
所以[i for x in ['b', 'c'] for i in ['a', x]]
变为:
for x in ['b', 'c']:
for i in ['a', x]:
i # added to the final list
和[i for i in ['a', x] for x in ['b', 'c']]
变为:
for i in ['a', x]:
for x in ['b', 'c']:
i
如您所见,如果没有先在列表理解范围之外定义x
,则第二个版本将无法运行,因为否则无法创建['a', x]
列表.还要注意,内循环for x in ['b', 'c']
的x
会被忽略.您得到的只是重复i
.内循环中该列表中的值是什么都没关系,仅循环的长度不再重要.
As you can see, the second version would not be able to run without first defining x
outside of your list comprehension, because otherwise the ['a', x]
list could not be created. Also note that the x
for the inner loop for x in ['b', 'c']
is otherwise ignored. All you get is i
repeated. It doesn't matter what the values are in that list in the inner loop, only the length of the loop matters anymore.
在您的情况下,将首先设置x = 'c'
来解释您的输出;那么对于外循环,您得到for i in ['a', 'c']
,对内循环进行两次迭代,因此将'a'
添加了两次,然后设置了i = 'c'
并两次将'c'
添加了.
In your case, your output would be explained by setting x = 'c'
first; then you get for i in ['a', 'c']
for the outer loop, the inner loop iterates twice so 'a'
is added twice, then i = 'c'
is set and you get 'c'
added twice.
碰巧,在Python 2中,列表理解'leak'中使用的变量,就像常规for
循环泄漏中使用的变量一样;使用for x in ['b', 'c']: pass
后,x
将保持可用并绑定到'c'
.这是您的x = 'c'
来源:
As it happens, in Python 2, the variables using in a list comprehension 'leak', just like the variables used in a regular for
loop leak; after using for x in ['b', 'c']: pass
, x
would remain available and bound to 'c'
. This is where your x = 'c'
comes from:
>>> [i for x in ['b', 'c'] for i in ['a', x]]
['a', 'b', 'a', 'c']
>>> i
'c'
>>> x
'c'
>>> [i for i in ['a', x] for x in ['b', 'c']]
['a', 'a', 'c', 'c']
i
和x
反映了它们最后绑定到的内容,因此运行下一个列表理解是在第一个( outer )循环遍历['a', 'c']
时工作的.
i
and x
reflect what they were last bound to, so running the next list comprehension works as the first (outer) loop iterates over ['a', 'c']
.
从全局变量中删除x
,并且第二个列表理解完全无法运行:
Remove x
from your globals and the second list comprehension simply fails to run:
>>> del x
>>> [i for i in ['a', x] for x in ['b', 'c']]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
上述完整的常规for
循环版本也是如此:
The same happens to the full regular for
loop versions above:
>>> for i in ['a', x]:
... for x in ['b', 'c']:
... i
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> x = 'foo'
>>> for i in ['a', x]:
... for x in ['b', 'c']:
... i
...
'a'
'a'
'foo'
'foo'
在Python 3中,列表推导是在新作用域中执行的(就像生成器表达式,dict推导和set推导已经在Python 2中一样).
In Python 3, list comprehensions are executed in a new scope (just like generator expressions, dict comprehensions and set comprehensions already do in Python 2).
这篇关于列表理解中for语句的顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!