1つの答えはなく、真で唯一のものではありません。多くの変数の中では、次の要素に依存します。
- データセットのサイズ。
- ユニークキーの数。
- defaultdictの基礎となる工場の速度。
- OrderDictのスピードとその後の注文ステップ。
- Pythonのバージョン。
は、私はいくつかの一般論を一般化する嫌うをですが、ここでは、次のとおりです。
- 声明
This technique is simpler and faster than an equivalent technique using dict.setdefault()
はちょうどフラット間違っています。それはデータに依存します。
setdefault
は、小さなデータセットではより高速で簡単です。
defaultdict
は、より均質なキーセットを持つより大きいデータセットの方が高速です。
setdefault
は、より異機種のキーセットで利点があります。
- これらの結果は、Python 3とPython 2では異なります。
OrderedDict
は、順序や順序に依存するアルゴリズム以外のすべての場合において、再構成または並べ替えが容易ではありません。
- ほとんどの場合、Python 3はほとんどの操作が高速です。
- Python 3.6のdictが挿入命令で注文されるようになりました。
唯一の真実:それに依存します! 3つの手法はすべて役に立ちます。ここ
を示すいくつかのタイミング・コードである:
from __future__ import print_function
from collections import defaultdict
from collections import OrderedDict
try:
t=unichr(100)
except NameError:
unichr=chr
def f1(li):
'''defaultdict'''
d = defaultdict(list)
for k, v in li:
d[k].append(v)
return d.items()
def f2(li):
'''setdefault'''
d={}
for k, v in li:
d.setdefault(k, []).append(v)
return d.items()
def f3(li):
'''OrderedDict'''
d=OrderedDict()
for k, v in li:
d.setdefault(k, []).append(v)
return d.items()
if __name__ == '__main__':
import timeit
import sys
print(sys.version)
few=[('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
fmt='{:>12}: {:10.2f} micro sec/call ({:,} elements, {:,} keys)'
for tag, m, n in [('small',5,10000), ('medium',20,1000), ('bigger',1000,100), ('large',5000,10)]:
for f in [f1,f2,f3]:
s = few*m
res=timeit.timeit("{}(s)".format(f.__name__), setup="from __main__ import {}, s".format(f.__name__), number=n)
st=fmt.format(f.__doc__, res/n*1000000, len(s), len(f(s)))
print(st)
s = [(unichr(i%0x10000),i) for i in range(1,len(s)+1)]
res=timeit.timeit("{}(s)".format(f.__name__), setup="from __main__ import {}, s".format(f.__name__), number=n)
st=fmt.format(f.__doc__, res/n*1000000, len(s), len(f(s)))
print(st)
print()
パイソン2.7結果:
2.7.5 (default, Aug 25 2013, 00:04:04)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]
defaultdict: 10.20 micro sec/call (25 elements, 3 keys)
defaultdict: 21.08 micro sec/call (25 elements, 25 keys)
setdefault: 13.41 micro sec/call (25 elements, 3 keys)
setdefault: 18.24 micro sec/call (25 elements, 25 keys)
OrderedDict: 49.47 micro sec/call (25 elements, 3 keys)
OrderedDict: 102.16 micro sec/call (25 elements, 25 keys)
defaultdict: 28.28 micro sec/call (100 elements, 3 keys)
defaultdict: 79.78 micro sec/call (100 elements, 100 keys)
setdefault: 45.68 micro sec/call (100 elements, 3 keys)
setdefault: 68.66 micro sec/call (100 elements, 100 keys)
OrderedDict: 117.78 micro sec/call (100 elements, 3 keys)
OrderedDict: 343.17 micro sec/call (100 elements, 100 keys)
defaultdict: 1123.60 micro sec/call (5,000 elements, 3 keys)
defaultdict: 4250.44 micro sec/call (5,000 elements, 5,000 keys)
setdefault: 2089.86 micro sec/call (5,000 elements, 3 keys)
setdefault: 3803.03 micro sec/call (5,000 elements, 5,000 keys)
OrderedDict: 4399.16 micro sec/call (5,000 elements, 3 keys)
OrderedDict: 16279.14 micro sec/call (5,000 elements, 5,000 keys)
defaultdict: 5609.39 micro sec/call (25,000 elements, 3 keys)
defaultdict: 25351.60 micro sec/call (25,000 elements, 25,000 keys)
setdefault: 10267.00 micro sec/call (25,000 elements, 3 keys)
setdefault: 24091.51 micro sec/call (25,000 elements, 25,000 keys)
OrderedDict: 22091.98 micro sec/call (25,000 elements, 3 keys)
OrderedDict: 94028.00 micro sec/call (25,000 elements, 25,000 keys)
パイソン3.3結果:
3.3.2 (default, May 21 2013, 11:50:47)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))]
defaultdict: 8.58 micro sec/call (25 elements, 3 keys)
defaultdict: 21.18 micro sec/call (25 elements, 25 keys)
setdefault: 10.42 micro sec/call (25 elements, 3 keys)
setdefault: 14.58 micro sec/call (25 elements, 25 keys)
OrderedDict: 45.43 micro sec/call (25 elements, 3 keys)
OrderedDict: 92.69 micro sec/call (25 elements, 25 keys)
defaultdict: 20.47 micro sec/call (100 elements, 3 keys)
defaultdict: 77.48 micro sec/call (100 elements, 100 keys)
setdefault: 34.22 micro sec/call (100 elements, 3 keys)
setdefault: 54.86 micro sec/call (100 elements, 100 keys)
OrderedDict: 107.37 micro sec/call (100 elements, 3 keys)
OrderedDict: 318.98 micro sec/call (100 elements, 100 keys)
defaultdict: 714.70 micro sec/call (5,000 elements, 3 keys)
defaultdict: 3892.92 micro sec/call (5,000 elements, 5,000 keys)
setdefault: 1502.91 micro sec/call (5,000 elements, 3 keys)
setdefault: 2888.08 micro sec/call (5,000 elements, 5,000 keys)
OrderedDict: 3912.95 micro sec/call (5,000 elements, 3 keys)
OrderedDict: 14863.02 micro sec/call (5,000 elements, 5,000 keys)
defaultdict: 3649.02 micro sec/call (25,000 elements, 3 keys)
defaultdict: 22313.17 micro sec/call (25,000 elements, 25,000 keys)
setdefault: 7447.28 micro sec/call (25,000 elements, 3 keys)
setdefault: 18426.88 micro sec/call (25,000 elements, 25,000 keys)
OrderedDict: 19202.17 micro sec/call (25,000 elements, 3 keys)
OrderedDict: 85946.45 micro sec/call (25,000 elements, 25,000 keys)
を 'defaultdict'は必ずしも正規よりも遅くありません'dict'。タイミングには欠陥があります。タイミング*にはオブジェクトの作成*が含まれます。それ以外に、さまざまなタイプのパフォーマンスがあり、メンテナンスが容易です。パフォーマンスを測定する基準は指定していません。 **仕事のための**正しいツールを使用してください。 –
もう一度やり直してください:あなたのユースケースの*独自のタイミングを実行してください。あなたが挙げるタイミングは、小さなデータセットのためのものであり、辞書オブジェクトの作成を含みます。なぜなら、小さなデータセットで不公平に結果を歪める 'defaultdict(...)'ファクトリコール(グローバルルックアップ、スタックプッシュ、呼び出し)よりも、dictリテラル( '{}')が* far * 'defaultdict'の方が遅いという前提には欠陥があります。 –
私は 'defaultdict'が' dict.setdefault'を呼び出さなければならないことにしばしば同意しますが、なぜ 'OrderedDict'が' dict'に対して「可能な限り優先」されるのですか?私は、キーが辞書に挿入された順序について気にしていなかったと思います。これは単に新しいキーのデフォルト値を提供するよりもはるかに特有の機能です。 – chepner