列表理解中的语句顺序

时间:2015-09-11 19:28:44

标签: python python-2.7 list-comprehension

在python2.7中,我试图将字符串列表中的每个项目添加到另一个项目中(例如,在列表['b','c']中的每个项目之前添加项目'a')。从How to add list of lists in a list comprehension开始,我确定了正确的命令,归结为:

>>> [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'条目发生了什么?

1 个答案:

答案 0 :(得分:9)

列表推导中的\循环始终以嵌套顺序列出。您可以使用相同的嵌套顺序将两种理解都写成常规循环;请记住,只有第一个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]的{​​{1}}否则将被忽略。所有你得到的是x重复。在内循环中该值列表中的值并不重要,只有循环的长度才重要

在您的情况下,您的输出将通过首先设置for x in ['b', 'c']来解释;然后你获得外部循环的i,内循环迭代两次,因此x = 'c'被添加两次,然后设置for i in ['a', 'c'],你得到'a'两次。

实际上,在Python 2中,变量使用列表理解和泄漏,就像常规i = 'c'循环泄漏中使用的变量一样;使用'c'后,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

在Python 3中,列表推导在新范围内执行(就像生成器表达式,dict理解和集合理解已经在Python 2中执行)。