17

I'm reading the Python wikibook and feel confused about this part:

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']

I understand the usage of nested for loops but I don't get

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

What does this mean? (shorter, longer...)

4

2 に答える 2

22

これらのタイプのネストされたループは、2 つのシーケンスのデカルト積を作成します。それを試してみてください:

>>> [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'と同じです。 for x in 'cat':

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

したがって、一方を短くしたり長くしたりする効果は、ネストされた 2 つのループで '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']

'x' が外側のループである 2 つのネストされた 'for' ループと同じです。

ネストされたループは、外側のループ時間yの範囲で内側のループを実行し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'] 

itertoolsのproductでも同じ結果が得られます。

>>> 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 する zip にitertoolsを使用できますが、結果は異なります。

>>> import itertools
>>> [x+y for x,y in itertools.zip_longest('12345','ab',fillvalue='*')]
['1a', '2b', '3*', '4*', '5*'] 
于 2013-09-06T04:29:57.607 に答える