CPythonの同じアイテムのリストを反復some_dict.items()
処理するのと同じくらい効率的ですか?
3 に答える
使用しているPythonのバージョンによって異なります。Python 2ではsome_dict.items()
、新しいリストを作成します。これには、追加の時間がかかり、追加のメモリを消費します。一方、リストが作成されると、それはリストであるため、リスト作成のオーバーヘッドが完了した後は、同じパフォーマンス特性を持つはずです。
Python 3ではsome_dict.items()
、リストの代わりにビューオブジェクトを作成します。何もコピーする必要がないため、Python2よりも作成と反復処理のitems()
方が高速であると思います。しかし、辞書データはややまばらに保存されているため、作成済みのビューを反復処理する方が、作成済みのリストを反復処理するよりも少し遅くなることも予想されます。Pythonが、のすべてのビンを反復処理することを回避する良い方法はないと思います。辞書-空のものでさえ。
Python 2では、いくつかのタイミングで私の直感が確認されます。
>>> some_dict = dict(zip(xrange(1000), reversed(xrange(1000))))
>>> some_list = zip(xrange(1000), xrange(1000))
>>> %timeit for t in some_list: t
10000 loops, best of 3: 25.6 us per loop
>>> %timeit for t in some_dict.items(): t
10000 loops, best of 3: 57.3 us per loop
の反復items
は約2倍遅くなります。使用するiteritems
のは少し速いです...
>>> %timeit for t in some_dict.iteritems(): t
10000 loops, best of 3: 41.3 us per loop
ただし、リスト自体を反復処理することは、基本的に他のリストを反復処理することと同じです。
>>> some_dict_list = some_dict.items()
>>> %timeit for t in some_dict_list: t
10000 loops, best of 3: 26.1 us per loop
Python 3は、Python 2よりも高速に作成および反復できますitems
(上記の57.3 usと比較してください)。
>>> some_dict = dict(zip(range(1000), reversed(range(1000))))
>>> %timeit for t in some_dict.items(): t
10000 loops, best of 3: 33.4 us per loop
ただし、ビューを作成する時間はごくわずかです。実際には、リストよりも反復処理に時間がかかります。
>>> some_list = list(zip(range(1000), reversed(range(1000))))
>>> some_dict_view = some_dict.items()
>>> %timeit for t in some_list: t
10000 loops, best of 3: 18.6 us per loop
>>> %timeit for t in some_dict_view: t
10000 loops, best of 3: 33.3 us per loop
つまり、Python 3では、ディクショナリ内のアイテムを何度も反復処理する必要があり、パフォーマンスが重要な場合は、ビューをリストとしてキャッシュすることで30%高速化できます。
>>> some_list = list(some_dict_view)
>>> %timeit for t in some_list: t
100000 loops, best of 3: 18.6 us per loop
小さなベンチマークは、リストの反復が間違いなく高速であることを示しています。
def iterlist(list_):
i = 0
for _ in list_:
i += 1
return i
def iterdict(dict_):
i = 0
for _ in dict_.iteritems():
i += 1
return i
def noiterdict(dict_):
i = 0
for _ in dict_.items():
i += 1
return i
list_ = range(1000000)
dict_ = dict(zip(range(1000000), range(1000000)))
Python 2.7(Kubuntu)でIPythonを使用してテスト済み:
%timeit iterlist(list_)
10 loops, best of 3: 28.5 ms per loop
%timeit iterdict(dict_)
10 loops, best of 3: 39.7 ms per loop
%timeit noiterdict(dict_)
10 loops, best of 3: 86.1 ms per loop
反復処理some_list
はの2倍some_dict.items()
の速度向上ですが、インデックスによる反復処理は、キーによる some_list
反復処理とほぼ同じです。some_dict
K = 1000000
some_dict = dict(zip(xrange(K), reversed(xrange(K))))
some_list = zip(xrange(K), xrange(K))
%timeit for t in some_list: t
10 loops, best of 3: 55.7 ms per loop
%timeit for i in xrange(len(some_list)):some_list[i]
10 loops, best of 3: 94 ms per loop
%timeit for key in some_dict: some_dict[key]
10 loops, best of 3: 115 ms per loop
%timeit for i,t in enumerate(some_list): t
10 loops, best of 3: 103 ms per loop