循环的Python列表理解

2024-04-24 06:33:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我在读the Python wikibook,对这一部分感到困惑:

List comprehension supports more than one for statement. It will evaluate the items in all of the objects sequentially and will loop over the shorter objects if one object is longer than the rest.

>>>item = [x+y for x in 'cat' for y in 'pot']
>>>print item
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt']

我知道嵌套for循环的用法,但我不明白

...and will loop over the shorter objects if one object is longer than the rest

这是什么意思?(短,长…)


Tags: andtheinloopforifobjectsobject
2条回答

好吧,Python文档没有提到任何这样的短/长情况:http://docs.python.org/2/tutorial/datastructures.html#list-comprehensions。在列表理解中有两个“for”意味着有两个循环。@drewk所指的例子是正确的。

为了解释,让我抄一下:

>>> [x+y for x in '123' for y in 'pot']
['1p', '1o', '1t', '2p', '2o', '2t', '3p', '3o', '3t']
>>>
>>> [x+y for x in '1' for y in 'pot']
['1p', '1o', '1t']
>>>

在这两种情况下,第一个“for”形成外环,第二个“for”形成内环。这是这里唯一不变的。

这些类型的嵌套循环创建两个序列的Cartesian Product。试试看:

>>> [x+y for x in 'cat' for y in 'potty']
['cp', 'co', 'ct', 'ct', 'cy', 'ap', 'ao', 'at', 'at', 'ay', 'tp', 'to', 'tt', 'tt', 'ty']
>>> [x+y for x in 'catty' for y in 'pot']
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt', 'tp', 'to', 'tt', 'yp', 'yo', 'yt']

上面列表理解中的“x”(即for x in 'cat'部分)与本例中的“x”相同:

>>> li=[]
>>> for x in 'cat':
...    for y in 'pot':
...       li.append(x+y)
# li=['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt']

因此,缩短或延长一个循环的效果与在两个嵌套循环中延长“x”或“y”循环的效果相同:

>>> li=[]
>>> for x in 'catty':
...    for y in 'pot':
...       li.append(x+y)
... 
>>> li==[x+y for x in 'catty' for y in 'pot']
True

在每种情况下,较短的序列都会再次循环,直到较长的序列耗尽为止。这与zip不同,后者将在较短序列的末尾终止配对。

编辑

对于嵌套循环和zip(在注释中)似乎存在混淆。

嵌套循环:

如上图所示:

[x+y for x in '12345' for y in 'abc']

与两个嵌套的“for”循环相同,外部循环为“x”。

嵌套循环将在外部循环时间内执行内部循环。

所以:

>>> [x+y for x in '12345' for y in 'ab']
    ['1a', '1b',   # '1' in the x loop
     '2a', '2b',   # '2' in the x loop, b in the y loop
     '3a', '3b',   # '3' in the x loop, back to 'a' in the y loop
     '4a', '4b',   # so on
     '5a', '5b'] 

使用product可以从itertools获得相同的结果:

>>> from itertools import product
>>> [x+y for x,y in product('12345','ab')]
['1a', '1b', '2a', '2b', '3a', '3b', '4a', '4b', '5a', '5b']

Zip与相似,但在较短的序列耗尽后停止:

>>> [x+y for x,y in zip('12345','ab')]
['1a', '2b']
>>> [x+y for x,y in zip('ab', '12345')]
['a1', 'b2']

您可以对zip使用itertools,该zip将一直压缩到最长的序列用完为止,但结果不同:

>>> import itertools
>>> [x+y for x,y in itertools.zip_longest('12345','ab',fillvalue='*')]
['1a', '2b', '3*', '4*', '5*'] 

相关问题 更多 >