为什么使用切片[:]比使用明显的方式更快地复制列表?

时间:2014-04-01 20:23:24

标签: python performance list cpython shallow-copy

为什么使用切片对列表进行浅层复制比使用list内置文件快得多?

In [1]: x = range(10)

In [2]: timeit x_ = x[:]
10000000 loops, best of 3: 83.2 ns per loop

In [3]: timeit x_ = list(x)
10000000 loops, best of 3: 147 ns per loop

通常当我看到这样奇怪的事情时,它们会在python3中修复 - 但这种差异仍然存在:

In [1]: x = list(range(10))

In [2]: timeit x_ = x[:]
10000000 loops, best of 3: 100 ns per loop

In [3]: timeit x_ = list(x)
10000000 loops, best of 3: 178 ns per loop

1 个答案:

答案 0 :(得分:9)

区别在于额外的函数调用(只有SLICE+0 vs CALL_FUNCTION 1 额外的堆栈操作):

>>> import dis
>>> def f(lst):
...  return lst[:]
... 
>>> def f1(lst):
...  return list(lst)
... 
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (lst)
              3 SLICE+0             
              4 RETURN_VALUE        
>>> dis.dis(f1)
  2           0 LOAD_GLOBAL              0 (list)
              3 LOAD_FAST                0 (lst)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE 

来自dis docs

  

<强> SLICE + 0()
  实现TOS = TOS [:]。

(TOS - 堆栈顶部)

  

<强> CALL_FUNCTION(argc个)
  调用一个函数。 argc的低字节表示   位置参数的数量,高字节的数量   关键字参数。在堆栈上,操作码找到关键字   参数首先。对于每个关键字参数,值都在上面   钥匙。在关键字参数下方,位置参数是   在堆栈上,最右边的参数位于顶部。以下   参数,要调用的函数对象在堆栈上。一切都流行起来   函数参数,以及函数本身离开堆栈,并推送   返回值。