4

csvPython の非常に貴重なモジュールを使用して、大きな csv ファイル (400 万行以上) を読み込んでいます。さまざまなアプローチのタイミングを計る中で、直感的でない結果に出くわしました。

次のスクリプトを実行すると、約11 ~ 12 秒かかります。 bの後、ほぼ瞬時に作成されaます。

r = csv.reader(open("data.csv", "rb"), delimiter=";")
a = [None for row in r]
b = [row for row in r]

しかし、まったく作成しない同様のスクリプトを実行するとa、コードに時間がかかります( 21-22)。

r = csv.reader(open("data.csv", "rb"), delimiter=";")
b = [row for row in r]

bが作成された後、 の作成にほとんど時間がかからない理由が理解できaます。しかし、私は (素朴に) のみbが作成され、 が作成されない2 番目のコード ブロックaの方が高速なスクリプトになると考えていました。非 Pythonic のように見えるリスクがありますが作成する理由を誰かが説明できるかどうかを知りたいと思っています。abb

さらに、この速度向上がより複雑な操作で一貫している場合、(スタイル/読みやすさの問題以外に)それを利用しない正当な理由はありますか? 聞いたことのない従来の方法で同じ時間の節約をすでに達成しているよりも、Python プログラマーの方が精通しているでしょうか?

aたとえば、の代わりに整数を使用して構築するとNone、同じ結果が得られます。csv.readerオブジェクトを反復処理するのではなく、 を反復処理する場合、open("data.csv", "rb").readlines()タイミングは予想どおりbです。したがって、時間のずれはおそらく、オブジェクトのプロパティ、またはそのようなオブジェクトのより一般的なクラスのプロパティと関係があります。より前に作成した場合、時間は 1 人で作成した場合とほぼ同じです。 abcsv.readerbab

いくつかのメモ:

  • b前に作成すると、単独でa作成するのと同じ時間がかかります。b
  • これらを対話モードで行ごとに実行していません。それぞれを個別のスクリプトとして実行しています。
  • と同じ長さのものでいっぱいのrリスト、または の行のリストを実際に作成しようとしているわけではありませんr
  • 念のために言うと、私は 64 ビット Windows 7 で Enthought Python ディストリビューション 7.3-2 を使用して Python 2.7.3 を実行しています。
4

2 に答える 2

6

最初の例を見たことがbありますか?r最初のリスト内包表記で使い果たされたため、空です。すべての行はすでに反復されており、@soulcheck が指摘したように、None400 万のサブリストを含むリストよりも 400 万のリストを作成する方がはるかに高速です。

于 2013-04-06T20:58:54.423 に答える
3

これにより、いくつかの洞察が得られる場合があります。10 行の csv ファイルの短い例を見て、これを比較してみましょう。

import csv
from collections import Counter

r = csv.reader(open('foo.csv'))
a = [id(row) for row in r]

r = csv.reader(open('foo.csv'))
b = [row for row in r]
b_id = [id(row) for row in b]

c1 = Counter(a)
c2 = Counter(b_id)

print c1
print c2

これにより、

Counter({139713821424456: 5, 139713821196512: 5})
Counter({139713821196512: 1, 139713821669136: 1, 139713821668776: 1, 139713821196584: 1, 139713821669064: 1, 139713821668560: 1, 139713821658792: 1, 139713821668704: 1, 139713821668848: 1, 139713821668632: 1})

つまり、 ではa、同じメモリを何度も再利用しました。のリスト内包a表記は への参照を保持しないため、rowすぐにガベージ コレクションが行われ、そのメモリが再利用のために開かれます。そのままにしておくと、当然、新しいリストごとにメモリを割り当てる必要があります。

于 2013-04-06T21:28:38.670 に答える