web-dev-qa-db-ja.com

Pythonでは、リスト内包表記またはfor-eachループを使用する方が良いですか?

次のうちどれを使用するのが良いですか、そしてその理由は何ですか?

方法1:

for k, v in os.environ.items():
       print "%s=%s" % (k, v)

方法2:

print "\n".join(["%s=%s" % (k, v) 
   for k,v in os.environ.items()])

私は最初の方をより理解しやすいものに導く傾向がありますが、それは私がPythonに慣れておらず、リスト内包表記がまだ私にとって少し異質であるためかもしれません。2番目の方法はよりPythonicと見なされますか?パフォーマンスに違いはないと思いますが、間違っているかもしれませんが、この2つのテクニックの長所と短所は何でしょうか。

(コードは Dive into Python

37
froadie

副作用のために反復が行われている場合(「印刷」の例のように)、ループはより明確になります。

複合値を作成するために反復が実行される場合、リスト内包表記は通常、より読みやすくなります。

38

選択した特定のコード例は、リスト内包表記の利点を示していません。これは、リスト内包表記が印刷という簡単なタスクに(誤)使用されているためです。この単純なケースでは、単純なforループを選択します。

他の多くの場合、実際のリストを別の関数またはメソッドに提供する必要があります。リスト内包表記は、それを行うための最も簡単で読みやすい方法です。

リストコンプの優位性を明確に示す例は、printループの反復ごとに追加することにより、forの例を別の実際のリストの作成を伴う例に置き換えることで作成できます。

L = []
for x in range(10):
    L.append(x**2)

次と同じLを与えます。

L = [x**2 for x in range(10)]
25
Ben James

最初の例の方が優れていると思います。冗長性が低く、明確で、読みやすくなっています。

私の意見では、結局のところ、あなたの意図を最もよく伝えるものを選んでください:

プログラムは、人々が読むことができるように、そして偶然にマシンが実行できるように作成する必要があります。

--AbelsonとSussmanによる「コンピュータプログラムの構造と解釈」から

ちなみに、Pythonを学び始めたばかりなので、すぐに 新しい文字列フォーマット構文 の学習を始めてください。

for k, v in os.environ.items():
    print "{0}={1}".format(k, v)
15
Tim Pietzcker

リスト内包表記は、明示的なループの2倍以上高速です。ベンジェームスのバリエーションに基づいていますが、x ** 2をより簡単なx + 2関数に置き換えて、2つの選択肢は次のとおりです。

def foo(n):
  L = []
  for x in xrange(n):
    L.append(x+2)
  return L


def bar(n):
  return [x+2 for x in xrange(n)]

タイミング結果:

In [674]: timeit foo(1000)
10000 loops, best of 3: 195 us per loop

In [675]: timeit bar(1000)
10000 loops, best of 3: 81.7 us per loop

リスト内包表記は大幅に勝ちます。

私は、読みやすさがパフォーマンスの最適化よりも優先されるべきであることに同意します。しかし、読みやすさは見る人の目にあります。私が最初にPythonを学んだとき、リスト内包表記は私が理解するのが難しいと思う奇妙なことです! :-Oしかし、慣れると、本当に素敵な速記法になります。 Pythonに習熟する場合は、リスト内包表記をマスターする必要があります。

13
Wai Yip Tung

私の意見の最初のもの、理由:

  • 巨大な文字列は作成されません。
  • 巨大なリストは作成されません([]を削除することで、ジェネレーターで簡単に修正できます)。

どちらの場合も、同じ方法でアイテムにアクセスします(ディクショナリイテレータを使用)。

4

リスト内包表記は経営幹部レベルで実行されることになっているため、巨大なループがある場合は、リスト内包表記を選択することをお勧めします。

3
YOU

@ Ben、@ Tim、@ Stevenに同意します:

  • 読みやすさは最も重要なことです(「これをインポート」して、何であるかを思い出してください)
  • listcompは、反復ループバージョンよりもはるかに高速である場合とそうでない場合があります...実行される関数呼び出しの総数によって異なります
  • do大きなデータセットでlistcompsを使用することにした場合は、代わりにジェネレータ式を使用することをお勧めします。

例:

_print "\n".join("%s=%s" % (k, v) for k,v in os.environ.iteritems())
_

上記のコードスニペットでは、two変更を加えました... listcompをgenexpに置き換え、メソッド呼び出しをiteritems()に変更しました。 [この傾向は、Python 3、iteritems()が置き換えられ、items()に名前が変更されたように進んでいます。]

2
wescpy