Python:迭代列表与dict项目效率

时间:2012-09-22 12:38:17

标签: python performance list dictionary

迭代some_dict.items()和迭代CPython中相同项的列表一样有效吗?

3 个答案:

答案 0 :(得分:23)

这取决于您使用的是哪个版本的Python。在Python 2中,some_dict.items()创建了一个新列表,它占用了一些额外的时间并耗尽了额外的内存。另一方面,一旦创建了列表,它就是一个列表,因此在列表创建的开销完成后应具有相同的性能特征。

在Python 3中,some_dict.items()创建了一个视图对象而不是列表,我预计在items()上创建和迭代将比在Python 2中更快,因为没有必要复制。但是我预计迭代已经创建的视图会比在已经创建的列表上迭代慢一点,因为字典数据的存储有点稀疏,我相信python没有好办法避免迭代字典中的每个bin - 甚至是空字符。

在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大约慢两倍。使用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我们相比):

>>> 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

答案 1 :(得分:7)

一个小基准测试表明,迭代列表肯定更快。

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

答案 2 :(得分:0)

尽管迭代some_list的速度是some_dict.items()的2倍,但按索引迭代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