この特定のケースでは、代わりにacollections.Counter()
またはcollections.defaultdict()
オブジェクトのいずれかを使用してください。
import collections
dct = collections.defaultdict(int)
for c in string:
dict[c] += 1
また
dct = collections.Counter(string)
どちらも標準dict
タイプのサブクラスです。このCounter
タイプは、2つのカウンターを合計したり、カウントされた最も一般的なエンティティを一覧表示したりするなど、より便利な機能を追加します。クラスにはdefaultdict
他のデフォルトタイプを指定することもできます。defaultdict(list)
たとえば、キーごとにリストにまとめるために使用します。
2つの異なるアプローチのパフォーマンスを比較する場合は、次のtimeit
モジュールを使用します。
>>> import timeit
>>> def intest(dct, values):
... for c in values:
... if c in dct:
... dct[c]+=1
... else:
... dct[c]=1
...
>>> def get(dct, values):
... for c in values:
... dct[c] = dct.get(c, 0) + 1
...
>>> values = range(10) * 10
>>> timeit.timeit('test(dct, values)', 'from __main__ import values, intest as test; dct={}')
22.210275888442993
>>> timeit.timeit('test(dct, values)', 'from __main__ import values, get as test; dct={}')
27.442166090011597
これは、使用in
が少し速いことを示しています。
ただし、考慮すべき3番目のオプションがあります。KeyError
例外をキャッチする:
>>> def tryexcept(dct, values):
... for c in values:
... try:
... dct[c] += 1
... except KeyError:
... dct[c] = 1
...
>>> timeit.timeit('test(dct, values)', 'from __main__ import values, tryexcept as test; dct={}')
18.023509979248047
これはたまたま最速です。新しいキーの場合は10件に1件だけだからです。
最後になりましたが、私が提案した2つの選択肢は次のとおりです。
>>> def default(dct, values):
... for c in values:
... dct[c] += 1
...
>>> timeit.timeit('test(dct, values)', 'from __main__ import values, default as test; from collections import defaultdict; dct=defaultdict(int)')
15.277361154556274
>>> timeit.timeit('Counter(values)', 'from __main__ import values; from collections import Counter')
38.657804012298584
したがって、Counter()
タイプは最も低速ですが、実際にdefaultdict
は非常に高速です。Counter()
ただし、より多くの作業を実行し、追加の機能により、開発が容易になり、他の場所で実行速度が向上する可能性があります。