Absolutely no difference between them, at least in Python 3. You can check the byte-code produced for each of these using dis.dis
if you'd like:
l = [1, 2, 3, 4]
Byte-code emitted for l[:]
:
from dis import dis
dis('l[:]')
1 0 LOAD_NAME 0 (l)
3 LOAD_CONST 0 (None)
6 LOAD_CONST 0 (None)
9 BUILD_SLICE 2
12 BINARY_SUBSCR
13 RETURN_VALUE
while, byte-code emitted for l[::]
:
dis('l[::]')
1 0 LOAD_NAME 0 (l)
3 LOAD_CONST 0 (None)
6 LOAD_CONST 0 (None)
9 BUILD_SLICE 2
12 BINARY_SUBSCR
13 RETURN_VALUE
as you can see, they're exactly the same. Both load some None
's (the two LOAD_CONSTS
's) for the values of start
and stop
used for building the slice (BUILD_SLICE
) and apply it. None
s are the default for these as stated in the docs for slices
in the Standard Type hierarchy:
Special read-only attributes: start
is the lower
bound; stop
is the upper bound; step
is the step
value; each is None
if omitted. These attributes can have any type.
Use [:]
, it's less key-strokes.
It's actually interesting to note that in Python 2.x
the byte code generated is different and, due to less commands for l[:]
it might be slightly more performant:
>>> def foo():
... l[:]
...
>>> dis(foo)
2 0 LOAD_GLOBAL 0 (l)
3 SLICE+0
4 POP_TOP
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
While, for l[::]
:
>>> def foo2():
... l[::]
...
>>> dis(foo2)
2 0 LOAD_GLOBAL 0 (l)
3 LOAD_CONST 0 (None)
6 LOAD_CONST 0 (None)
9 LOAD_CONST 0 (None)
12 BUILD_SLICE 3
15 BINARY_SUBSCR
16 POP_TOP
17 LOAD_CONST 0 (None)
20 RETURN_VALUE
Even though I haven't timed these (and I won't, the difference should be tiny) it seems that, due to simply less instructions needed, l[:]
might be slightly better.
This similarity doesn't of course exist only for lists; it applies to all Sequences in Python:
# Note: the Bytecode class exists in Py > 3.4
>>> from dis import Bytecode
>>>
>>> Bytecode('(1, 2, 3)[:]').dis() == Bytecode('(1, 2, 3)[::]').dis()
True
>>> Bytecode('"string"[:]').dis() == Bytecode('"string"[::]').dis()
True
similarly for others.