リスト内包表記は、この形式のシンタックス シュガーとして最初に Python に導入されました。
L = []
for innerseq in seq:
for item in innerseq:
LOOPS
if CONDITION:
L.append(BODY)
これは次のように変換されます。
[BODY for innerseq in seq for item in innerseq LOOPS if CONDITION]
変換をより明確にするために、for
式とif
条件が通常のループとまったく同じ順序で発生することに注意してfor
ください。これが、リスト内包表記が同じ順序を使用する理由です。
内包としてループを書き直すと、変更されるのはループの本体の配置だけです (通常は空のコンテナーを初期化する前にループが移動します)。ループに関する他のすべてはまったく同じままです。
あなたが好む選択肢 (あなたの「正しい方法」) はどちらも、はるかに混乱しているように見えます。ループの順序を逆にするか、内包表記のすべての節の順序を逆にします。つまり、次のいずれかです。
[BODY LOOPS[::-1] for item in innerseq for innerseq in seq if CONDITION]
または
[BODY if CONDITION LOOPS[::-1] for item in innerseq for innerseq in seq]
これらのいずれも、不必要に複雑な変換のように見えます。
また、他の言語でも、リスト内包表記で同じ順序のループを使用していることに注意してください。ここにいくつかのClojureがあります:
user=> ; using your suggested "right" order
user=> (for [x (range y) y (range 4)] (+ x y))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: y in this context, compiling:(NO_SOURCE_PATH:1)
user=> ; you need to use the same "wrong" order as Python
user=> (for [y (range 4) x (range y)] (+ x y))
(1 2 3 3 4 5)
Clojure は内包表記の「本体」を最後に置きますが、これは Python と同じです。
for
ループが車の走行距離計の数字のように配置されていると想像してみてください。右端のループが最も速く回転します。