3

2 つのリスト内包表記を見てください。それぞれに 2 つの for 句が含まれています。for 句が正しい順序であると、Python が混乱することがわかります。しかし、それらが間違っている場合は、Python で処理できます。なんで?

Python 3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> [x + y for x in range(y) for y in range(4)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>> [x + y for y in range(4) for x in range(y)]
[1, 2, 3, 3, 4, 5]
>>>
4

3 に答える 3

5

[x + y for x in range(y) for y in range(4)]

その場所でのyインrange(y)は不明です。に相当:

for x in range(y):
    for y in range(4):
        # x + y

詳細については、 PEP-0202を参照してください。

- The form [... for x... for y...] nests, with the last index
      varying fastest, just like nested for loops.
于 2013-04-02T14:30:45.897 に答える
3

これは素晴らしい質問です!

その答えは、大部分の Python とは異なり、これらのネストされた内包表記は、ユーザーが書きたい方法ではなく、インタープリターが読みたい方法で書かれているということです。

インタプリタは、内包表記を右から左に読み取ります。

[(this is interpreted last) for (this is interpreted first)]

ただし、各節は左から右に読むので、そこから抜け出す前にy in range(4) for x in range(y)何があるかを説明する必要があります。yrange(y)

理解を入れ子にすることを考えると、右から左に考えるので、混乱します。

于 2013-04-02T14:32:13.133 に答える
3

リスト内包表記は、この形式のシンタックス シュガーとして最初に 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ループが車の走行距離計の数字のように配置されていると想像してみてください。右端のループが最も速く回転します。

于 2013-04-02T14:41:17.957 に答える