为什么元组比 Python 中的列表快?

2022-01-19 00:00:00 python list performance tuples

问题描述

我刚刚阅读了 深入 Python" 元组比列表快".

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

tuple 是不可变的,list 是可变的,但是我不太明白为什么 tuple 更快.

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

有人对此做过性能测试吗?

Anyone did a performance test on this?


解决方案

报告的构建速度"比率仅适用于 constant 元组(其项目由文字表示的元组).仔细观察(并在你的机器上重复——你只需要在 shell/命令窗口中输入命令!)...:

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

我没有在 3.0 上进行测量,因为我当然没有它——它已经完全过时了,绝对没有理由保留它,因为 3.1 在各方面都优于它(Python 2.7,如果你可以升级到它,在每个任务中测量为比 2.6 快近 20%——正如你所见,2.6 比 3.1 快——所以,如果你认真关心性能,Python 2.7 真的是唯一的释放你应该去的!).

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!).

无论如何,这里的关键点是,在每个 Python 版本中,使用常量文字构建列表的速度与使用变量引用的值构建列表的速度大致相同,或者稍微慢一些;但是元组的行为非常不同——用常量字面量构建一个元组通常比用变量引用的值构建它的速度快三倍!你可能想知道这是怎么回事,对吧?-)

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

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

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

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

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!_)

相关文章