あなたはどちらがより効率的かを尋ねました。実行速度について話していると仮定すると、データが小さい場合は問題ありません。大きくて典型的な場合、「既に存在する」ケースは「辞書にない」ケースよりもはるかに頻繁に発生します。この観察は、いくつかの結果を説明しています。
timeit
以下は、ファイル読み取りのオーバーヘッドなしで速度を調査するためにモジュールで使用できるコードです。私は自由に 5 番目の方法を追加しました。これは競争力がなく、少なくとも 1.5.2 [テスト済み] 以降の任意の Python で実行されます。
from collections import defaultdict, Counter
def tally0(iterable):
# DOESN'T WORK -- common base case for timing
d = {}
for item in iterable:
d[item] = 1
return d
def tally1(iterable):
d = {}
for item in iterable:
if item in d:
d[item] += 1
else:
d[item] = 1
return d
def tally2(iterable):
d = {}
for item in iterable:
try:
d[item] += 1
except KeyError:
d[item] = 1
return d
def tally3(iterable):
d = defaultdict(int)
for item in iterable:
d[item] += 1
def tally4(iterable):
d = Counter()
for item in iterable:
d[item] += 1
def tally5(iterable):
d = {}
dg = d.get
for item in iterable:
d[item] = dg(item, 0) + 1
return d
通常の実行 (Windows XP の「コマンド プロンプト」ウィンドウで):
prompt>\python27\python -mtimeit -s"t=1000*'now is the winter of our discontent made glorious summer by this son of york';import tally_bench as tb" "tb.tally1(t)"
10 loops, best of 3: 29.5 msec per loop
結果は次のとおりです(ループあたりのミリ秒):
0 base case 13.6
1 if k in d 29.5
2 try/except 26.1
3 defaultdict 23.4
4 Counter 79.4
5 d.get(k, 0) 29.2
別のタイミング トライアル:
prompt>\python27\python -mtimeit -s"from collections import defaultdict;d=defaultdict(int)" "d[1]+=1"
1000000 loops, best of 3: 0.309 usec per loop
prompt>\python27\python -mtimeit -s"from collections import Counter;d=Counter()" "d[1]+=1"
1000000 loops, best of 3: 1.02 usec per loop
の速度Counter
はおそらく、部分的に Python コードで実装されているのに対し、defaultdict
完全に C で実装されているためです (少なくとも 2.7 では)。
Counter()
単なる「構文糖衣」ではないことに注意してください-それは完全な別名オブジェクトdefaultdict(int)
を実装しています-詳細についてはドキュメントを参照してください。派手な後処理が必要な場合は、ホイールを再発明する必要がなくなります。数を数えることだけが目的の場合は、 を使用します。bag
multiset
defaultdict
@Steven Rumbalski からの質問に応じて更新: """ iterable を Counter コンストラクターに移動するとどうなるか興味があります: d = Counter(iterable)? (私は python 2.6 を持っていて、テストできません。) " ""
tally6: 実行するだけでd = Count(iterable); return d
、60.0 ミリ秒かかります
ソース (SVN リポジトリの collections.py ) を見ることができます ...が Mapping インスタンスでないPython27\Lib\collections.py
場合の私の動作は次のとおりです。iterable
self_get = self.get
for elem in iterable:
self[elem] = self_get(elem, 0) + 1
そのコードをどこかで見たことがありますか? Python 1.5.2 で実行可能なコードを呼び出すためだけに、多くのキャリーオンがあります。:-O