Why is shallow-copying a list using a slice so much faster than using list
builtin?
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
Usually when I see weird things like this, they're fixed in python3 - but this discrepancy is still there:
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
The difference is in additional function call (just SLICE+0
vs CALL_FUNCTION 1
with extra stack operations):
>>> 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
From dis docs:
SLICE+0()
Implements TOS = TOS[:].
(TOS - top of stack)
CALL_FUNCTION(argc)
Calls a function. The low byte of argc indicates the number of positional parameters, the high byte the number of keyword parameters. On the stack, the opcode finds the keyword parameters first. For each keyword argument, the value is on top of the key. Below the keyword parameters, the positional parameters are on the stack, with the right-most parameter on top. Below the parameters, the function object to call is on the stack. Pops all function arguments, and the function itself off the stack, and pushes the return value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With