为什么元组比Python中的列表快? [英] Why is tuple faster than list in Python?

查看:397
本文介绍了为什么元组比Python中的列表快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚阅读了,元组比列表快".

元组是不可变的,列表是可变的,但我不太理解为什么元组更快.

有人对此进行过性能测试吗?

解决方案

所报告的构造速度"比率仅适用于恒定元组(其项由文字表示的元组).仔细观察(并在您的机器上重复-您只需要在shell/命令窗口中键入命令即可!)...

$ python3.1 -mtimeit -s'x,y,z=1,2,3' '[x,y,z]'
1000000 loops, best of 3: 0.379 usec per loop
$ python3.1 -mtimeit '[1,2,3]'
1000000 loops, best of 3: 0.413 usec per loop

$ python3.1 -mtimeit -s'x,y,z=1,2,3' '(x,y,z)'
10000000 loops, best of 3: 0.174 usec per loop
$ python3.1 -mtimeit '(1,2,3)'
10000000 loops, best of 3: 0.0602 usec per loop

$ python2.6 -mtimeit -s'x,y,z=1,2,3' '[x,y,z]'
1000000 loops, best of 3: 0.352 usec per loop
$ python2.6 -mtimeit '[1,2,3]'
1000000 loops, best of 3: 0.358 usec per loop

$ python2.6 -mtimeit -s'x,y,z=1,2,3' '(x,y,z)'
10000000 loops, best of 3: 0.157 usec per loop
$ python2.6 -mtimeit '(1,2,3)'
10000000 loops, best of 3: 0.0527 usec per loop

我没有在3.0上进行测量,因为我当然没有它-它已经完全过时了,绝对没有理由保留它,因为3.1在各个方面都优于它(Python 2.7 ,如果您可以升级到它,那么每个任务的速度要比2.6快将近20%,而2.6的速度要比3.1快-因此,如果您非常在意性能,Python 2.7确实是唯一的选择释放您应该去的地方!).

无论如何,关键是在每个Python版本中,从常量文字中构建列表的速度与从变量引用的值中构建的速度大致相同或略慢;但是元组的行为却大不相同-从常量文字中构建元组的速度通常是从变量引用的值中构建元组的速度的三倍!您可能想知道这怎么可能,对吧?-)

答案:由常量文字组成的元组可以很容易地被Python编译器识别为一个不变的常量文字本身:因此,当编译器将源代码转换为字节码并隐藏在常量中时,它实际上只构建了一次.相关功能或模块的常量表".当这些字节码执行时,它们只需要恢复预构建的常量元组-嘿,好了!-)

这种简单的优化无法应用于列表,因为列表是可变对象,因此至关重要的是,如果相同的表达式(如[1, 2, 3])执行两次(在循环中-timeit模块进行循环)代表您;-),每次都会重新构造一个新的新列表对象-并且这种构造(例如当编译器无法简单地将其标识为编译时常量和不可变对象时的元组构造)确实需要一点时间一会儿.

话虽这么说,元组构造(实际上两种构造都必须 发生)仍然是列表构建速度的两倍-并且 差异可以由元组的纯粹简单性来解释,其他答案已经反复提到.但是,这种简单性并不能解决六倍或更多倍的加速问题,正如您观察到的那样,如果您仅比较列表和元组的构造以及简单常量文字作为它们的项!_)

I've just read in "Dive into Python" that "tuples are faster than lists".

Tuple is immutable, and list is mutable, but I don't quite understand why tuple is faster.

Anyone did a performance test on this?

解决方案

The reported "speed of construction" ratio only holds for constant tuples (ones whose items are expressed by literals). Observe carefully (and repeat on your machine -- you just need to type the commands at a shell/command window!)...:

$ python3.1 -mtimeit -s'x,y,z=1,2,3' '[x,y,z]'
1000000 loops, best of 3: 0.379 usec per loop
$ python3.1 -mtimeit '[1,2,3]'
1000000 loops, best of 3: 0.413 usec per loop

$ python3.1 -mtimeit -s'x,y,z=1,2,3' '(x,y,z)'
10000000 loops, best of 3: 0.174 usec per loop
$ python3.1 -mtimeit '(1,2,3)'
10000000 loops, best of 3: 0.0602 usec per loop

$ python2.6 -mtimeit -s'x,y,z=1,2,3' '[x,y,z]'
1000000 loops, best of 3: 0.352 usec per loop
$ python2.6 -mtimeit '[1,2,3]'
1000000 loops, best of 3: 0.358 usec per loop

$ python2.6 -mtimeit -s'x,y,z=1,2,3' '(x,y,z)'
10000000 loops, best of 3: 0.157 usec per loop
$ python2.6 -mtimeit '(1,2,3)'
10000000 loops, best of 3: 0.0527 usec per loop

I didn't do the measurements on 3.0 because of course I don't have it around -- it's totally obsolete and there is absolutely no reason to keep it around, since 3.1 is superior to it in every way (Python 2.7, if you can upgrade to it, measures as being almost 20% faster than 2.6 in each task -- and 2.6, as you see, is faster than 3.1 -- so, if you care seriously about performance, Python 2.7 is really the only release you should be going for!).

Anyway, the key point here is that, in each Python release, building a list out of constant literals is about the same speed, or slightly slower, than building it out of values referenced by variables; but tuples behave very differently -- building a tuple out of constant literals is typically three times as fast as building it out of values referenced by variables! You may wonder how this can be, right?-)

Answer: a tuple made out of constant literals can easily be identified by the Python compiler as being one, immutable constant literal itself: so it's essentially built just once, when the compiler turns the source into bytecodes, and stashed away in the "constants table" of the relevant function or module. When those bytecodes execute, they just need to recover the pre-built constant tuple -- hey presto!-)

This easy optimization cannot be applied to lists, because a list is a mutable object, so it's crucial that, if the same expression such as [1, 2, 3] executes twice (in a loop -- the timeit module makes the loop on your behalf;-), a fresh new list object is constructed anew each time -- and that construction (like the construction of a tuple when the compiler cannot trivially identify it as a compile-time constant and immutable object) does take a little while.

That being said, tuple construction (when both constructions actually have to occur) still is about twice as fast as list construction -- and that discrepancy can be explained by the tuple's sheer simplicity, which other answers have mentioned repeatedly. But, that simplicity does not account for a speedup of six times or more, as you observe if you only compare the construction of lists and tuples with simple constant literals as their items!_)

这篇关于为什么元组比Python中的列表快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆