Question:
Faced such a situation, having a list:
a = [1, 2, 3]
I want to get a copy of it, making the new переменную
unique so that it does not refer to the address of the old one. I know of two constructs that essentially do the same thing:
b = a[:]
and
b = a.copy()
Both of them are correct and will give the same result, but are there fundamental differences between them ?
Answer:
The list.copy()
method was introduced in Python 3.3 . The reason for its introduction was to make the syntax more readable and because for other objects such as dict
and set
the .copy()
method already existed and it would make sense to make it available for list
as well.
Python handles these calls differently – a[:]
is handled by slice
, while a.copy()
is handled by calling the appropriate method:
In [50]: import dis
In [51]: dis.dis("a.copy()")
1 0 LOAD_NAME 0 (a)
2 LOAD_ATTR 1 (copy)
4 CALL_FUNCTION 0
6 RETURN_VALUE
In [52]: dis.dis("a[:]")
1 0 LOAD_NAME 0 (a)
2 LOAD_CONST 0 (None)
4 LOAD_CONST 0 (None)
6 BUILD_SLICE 2
8 BINARY_SUBSCR
10 RETURN_VALUE
Which one works faster?
for 10.000.000 elements:
In [47]: lst = list(range(10**7))
In [48]: %timeit lst[:]
119 ms ± 1.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [49]: %timeit lst.copy()
119 ms ± 1.84 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
for 10.000 items:
In [53]: lst = list(range(10**4))
In [54]: %timeit lst.copy()
44.1 µs ± 602 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [55]: %timeit lst[:]
45.6 µs ± 3.23 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
for 100 elements:
In [62]: lst = list(range(100))
In [63]: %timeit lst.copy()
456 ns ± 19.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [64]: %timeit lst[:]
458 ns ± 22.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
those. in terms of speed, they are almost the same.
What is the preferred syntax?
I find a.copy()
to be preferable because is explicit and clear, and besides that, if you have to replace a list ( list
) with a set ( set
) in the code, then the slicing syntax will not work for a set.
PS A lot of useful and related information can be found in the answers to a similar question in the English version of SO