报告的“构造速度”比率仅适用于恒定元组(其项目由字面量表示)。仔细观察(并在您的机器上重复 – 您只需要在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编译器识别为一个不可变的常量文字本身:因此它基本上只构建一次,当编译器将源代码转换为字节码,并保存在“常量表“的相关功能或模块。当这些字节码执行时,它们只需要恢复预建的常量元组 – hey presto! – )
这种简单的优化不能应用于列表,因为列表是一个可变对象,因此如果相同的表达式[例如[1,2,3])执行两次(在循环中 – timeit模块使循环开启你的代码;-),一个新的新的列表对象每次都被重新构造 – 并且该构造(像编译器不能简单地将其标识为编译时常量和不可变对象的构造一个元组)需要一点时间。
也就是说,元组构造(当两个结构实际上必须发生)仍然是列表构建的两倍快 – 这种差异可以由元组的简单性来解释,其他答案已经反复提到。但是,这种简单性不会导致6倍或更快的加速,因为你观察到如果你只比较列表和元组的构造与简单的常量文字作为他们的项目!_)