列表理解中for语句的顺序
问题内容:
在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]
无法创建列表。另请注意,否则将
忽略x
for内循环。您得到的一切都是重复的。内循环中该列表中的值是什么无关紧要, 仅 循环 的长度不再重要 。for x in ['b', 'c']
i
在您的情况下,将x = 'c'
首先设置来解释您的输出;然后获得for i in ['a', 'c']
外循环,内循环重复两次,因此'a'
被添加了两次,然后i = 'c'
被设置,并且被'c'
添加了两次。
碰巧的是,在Python 2中,变量在列表理解“泄漏”中使用,就像在常规for
循环泄漏中使用的变量一样;使用后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推导和set推导已在Python 2中一样)。