列表理解中for语句的顺序
Order of for statements in a list comprehension
在 python2.7 中,我试图在字符串列表中的每个项目前面加上另一个项目(例如,在列表 [[=20= 中的每个项目之前添加项目 'a' ], 'c']).从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'条目发生了什么?
列表理解中的 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
否则会 被忽略 。您得到的只是 i
重复。内循环中该列表中的值是什么并不重要,只有循环的长度再重要了。
在您的情况下,您的输出将通过首先设置 x = 'c'
来解释;然后你得到外循环的for i in ['a', 'c']
,内循环迭代两次所以'a'
被添加两次,然后i = 'c'
被设置并且你得到'c'
被添加两次。
碰巧,在Python 2中,列表理解中使用的变量'leak',就像在常规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
反映了它们最后绑定到的内容,因此 运行 下一个列表理解作为第一个(outer) 循环遍历 ['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 中,列表推导在新的范围内执行(就像生成器表达式、字典推导和集合推导已经在 Python 2 中执行)。
在 python2.7 中,我试图在字符串列表中的每个项目前面加上另一个项目(例如,在列表 [[=20= 中的每个项目之前添加项目 'a' ], 'c']).从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'条目发生了什么?
列表理解中的 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
否则会 被忽略 。您得到的只是 i
重复。内循环中该列表中的值是什么并不重要,只有循环的长度再重要了。
在您的情况下,您的输出将通过首先设置 x = 'c'
来解释;然后你得到外循环的for i in ['a', 'c']
,内循环迭代两次所以'a'
被添加两次,然后i = 'c'
被设置并且你得到'c'
被添加两次。
碰巧,在Python 2中,列表理解中使用的变量'leak',就像在常规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
反映了它们最后绑定到的内容,因此 运行 下一个列表理解作为第一个(outer) 循环遍历 ['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 中,列表推导在新的范围内执行(就像生成器表达式、字典推导和集合推导已经在 Python 2 中执行)。