[英]Order of for statements in a list comprehension
在python2.7中,我试图将字符串列表中的每个项目添加到另一个项目中(例如,在列表['b','c']中的每个项目之前添加项目'a')。 从如何在列表推导中添加列表列表 ,我已经确定了正确的命令,其归结为:
>>> [i for x in ['b', 'c'] for i in ['a', x]]
['a', 'b', 'a', 'c']
纯粹基于临时i和x变量,下面的版本似乎更具可读性。 但是,它给出了完全不同的结果。 为什么这不会给出相同的结果?
>>> [i for i in ['a', x] for x in ['b', 'c']]
['a', 'a', 'c', 'c']
更奇怪的是,'b'条目发生了什么?
列表推导中的for
循环始终以嵌套顺序列出。 您可以使用相同的嵌套顺序将两种理解都写成常规循环; 记住,只有前首先表达for
产生的最终值,所以就把该环路内。
所以[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
的内环for x in ['b', 'c']
。 你得到的是i
重复。 内循环中该列表中的值无关紧要, 只有循环的长度才重要 。
在您的情况下,您的输出将通过首先设置x = 'c'
来解释; 然后你for i in ['a', 'c']
为外循环得到for i in ['a', 'c']
,内循环迭代两次所以'a'
被加两次,然后i = 'c'
被设置并且你得到'c'
两次。
碰巧,在Python 2中,变量在列表中使用了解“泄漏”,就像常规for
循环泄漏中使用的变量一样; for x in ['b', 'c']: pass
使用for x in ['b', 'c']: pass
后for x in ['b', 'c']: pass
, x
将保持可用并绑定到'c'
。 这是你的x = 'c'
来自的地方:
>>> [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
反映了它们最后绑定的内容,因此当第一个( 外部 )循环遍历['a', 'c']
,运行下一个列表理解会起作用。
从你的全局变量中删除x
,第二个列表理解根本无法运行:
>>> 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
循环版本也是如此:
>>> 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理解和集合理解已经在Python 2中完成)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.