在Python中,为什么从数组读取比从列表读取慢?
我最近在学习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
类型是需要花时间的。