在Python中,为什么从数组读取比从列表读取慢?

9 投票
3 回答
2031 浏览
提问于 2025-04-16 01:26

我最近在学习Python,并且在用这个语言做很多练习。

我发现一个有趣的事情,就是当我从数组中读取数据时,速度几乎是从列表中读取的速度的一半。有人知道这是为什么吗?

这是我的代码:

from timeit import Timer
import array

t = 10000
l = range(t)
a = array.array('i', l)
def LIST():
    for i in xrange(t):
        l[i]

def ARRAY():
    for i in xrange(t):
        a[i]

print Timer(LIST).timeit(1000);
print Timer(ARRAY).timeit(1000);

输出结果是:

0.813191890717
1.16269612312

这表明从数组中读取数据的速度比从列表中慢。我认为数组的大小是固定的,而列表是动态的结构。所以我原以为数组会比列表更快。

有人能解释一下吗?

3 个回答

1

Python中的列表在某些方面很像普通的数组,但它们并不是Lisp语言中的列表。不过,它们可以快速地访问里面的元素。

11

列表(list)就像是“动态增长的向量”,有点像C++里的std::vector,但这并不影响我们随机访问它们的速度(它们可不是链表!)。列表里的每个条目都是指向Python对象的引用(也就是里面的东西):访问一个条目只需要在CPython中增加这个对象的引用计数(在其他一些更高级的垃圾回收实现中,甚至连这一步都不需要;-)。而数组里的条目则是原始的位和字节:要访问一个条目,需要根据那个二进制值新创建一个Python对象。所以,比如说:

$ python -mtimeit -s'import array; c=array.array("B", "bzap")' 'c[2]'
10000000 loops, best of 3: 0.0903 usec per loop
$ python -mtimeit -s'c=list("bzap")' 'c[2]'
10000000 loops, best of 3: 0.0601 usec per loop

访问一个条目多花30纳秒的时间,听起来也还不错;-)。

顺便提一下,timeit在命令行中使用起来要方便得多——它会自动选择重复次数,显示时间的单位等等。我总是这样用它(如果需要的话,可以导入一个自定义的模块来调用函数——但在这里其实没必要)——这比从模块里导入和使用方便多了!

7

把一个普通的整数转换成Python里的int类型是需要花时间的。

撰写回答