14

私は時々この種のものを見ます:

(k for k in (j for j in (i for i in xrange(10))))

今、これは本当に私の脳を曲げます、そして私はむしろそれがこのように提示されなかったと思います。

ネストされたループである場合よりもエレガントで読みやすい、これらのネストされた式を使用したユースケースや例はありますか?

編集:これを単純化する方法の例をありがとう。実は私が求めていたものではなく、エレガントな時期はあるのではないかと思っていました。

4

7 に答える 7

21

リスト内包表記構文が言語に導入されたPEP 202を確認してください。

あなたの例を理解するために、Guido自身からの簡単なルールがあります:

  • [... for x... for y...] の形式は、ネストされた for ループのように、最後のインデックスが最も速く変化するようにネストします。

また、あなたの質問に答える PEP 202 から:

根拠
    リスト内包表記は、より簡潔にリストを作成する方法を提供します
    map() と filter() および/またはネストされたループが
    現在使用されています。

そのような状況があれば、よりエレガントであることがわかります。ただし、forループは視覚的に簡単に解析できるため、複数のネストされたリスト内包表記は、ネストされた for ループよりもコード内で明確でない場合があります。

于 2009-03-16T00:39:51.147 に答える
15

1 つの行が複雑すぎることが心配な場合は、次のように分割できます。

(k for k in 
    (j for j in 
        (i for i in xrange(10))))

Python では、行の継続が少し奇妙に見えることにいつも気付きますが、これにより、それぞれが何をループしているかを簡単に確認できます。追加の代入/ルックアップは何かを成功させたり壊したりしないので、次のように書くこともできます:

gen1 = (i for i in xrange(10))
gen2 = (j for j in gen1)
gen3 = (k for k in gen2)

実際には、内包表記を 2 層以上入れ子にしたことはないと思いますが、その時点ではまだ非常に簡単に理解できました。

于 2009-03-15T22:41:50.883 に答える
6

あなたの例の場合、私はおそらく次のように書きます:

foos = (i for i in xrange(10))
bars = (j for j in foos)
bazs = (k for k in bars)

よりわかりやすい名前を付ければ、これはおそらく非常に明確になると思いますが、測定可能なパフォーマンスの違いがあるとは想像できません。

おそらく、次のような表現をもっと考えているでしょう。

(x for x in xs for xs in ys for ys in lst)

-- 実際、それは有効ではありません。別の順序で並べる必要があります。

(x for ys in lst for xs in ys for x in xs)

リストを平坦化する簡単な方法としてそれを書くかもしれませんが、一般的にはあなたが書いていると思います.lessを入力することで節約される時間は、通常、ジェネレーター式を正しくするために費やす余分な時間とバランスが取れています.

于 2009-03-15T22:41:06.987 に答える
4

これらはジェネレーター式であるため、それぞれを独自の名前にバインドして、パフォーマンスを変更せずに読みやすくすることができます。ネストされたループに変更すると、パフォーマンスが低下する可能性があります。

irange = (i for i in xrange(10))
jrange = (j for j in irange)
krange = (k for k in jrange)

どちらを選択しても問題ありません。一般的に、複数行の例の方が読みやすいと思います。

于 2009-03-15T22:40:38.297 に答える
0

表現:

(k for k in (j for j in (i for i in xrange(10))))

次と同等です。

(i for i in xrange(10))

それはほとんど同じです:

xrange(10)

最後のバリアントは、最初のバリアントよりもエレガントです。

于 2009-03-16T12:38:54.460 に答える