65

What is the best way to copy a list? I know the following ways, which one is better? Or is there another way?

lst = ['one', 2, 3]

lst1 = list(lst)

lst2 = lst[:]

import copy
lst3 = copy.copy(lst)
poke
  • 339,995
  • 66
  • 523
  • 574
sheats
  • 30,992
  • 14
  • 43
  • 43

7 Answers7

105

If you want a shallow copy (elements aren't copied) use:

lst2=lst1[:]

If you want to make a deep copy then use the copy module:

import copy
lst2=copy.deepcopy(lst1)
Mark Roddy
  • 25,486
  • 19
  • 65
  • 71
23

I often use:

lst2 = lst1 * 1

If lst1 it contains other containers (like other lists) you should use deepcopy from the copy lib as shown by Mark.


UPDATE: Explaining deepcopy

>>> a = range(5)
>>> b = a*1
>>> a,b
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
>>> a[2] = 55 
>>> a,b
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4])

As you may see only a changed... I'll try now with a list of lists

>>> 
>>> a = [range(i,i+3) for i in range(3)]
>>> a
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
>>> b = a*1
>>> a,b
([[0, 1, 2], [1, 2, 3], [2, 3, 4]], [[0, 1, 2], [1, 2, 3], [2, 3, 4]])

Not so readable, let me print it with a for:

>>> for i in (a,b): print i   
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
>>> a[1].append('appended')
>>> for i in (a,b): print i

[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]]
[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]]

You see that? It appended to the b[1] too, so b[1] and a[1] are the very same object. Now try it with deepcopy

>>> from copy import deepcopy
>>> b = deepcopy(a)
>>> a[0].append('again...')
>>> for i in (a,b): print i

[[0, 1, 2, 'again...'], [1, 2, 3, 'appended'], [2, 3, 4]]
[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]]
Andrea Ambu
  • 36,488
  • 14
  • 52
  • 76
  • 2
    `copy()` will not work in the last case, you need `deepcopy()` whenever you have a reference inside the object. – Aram Kocharyan Sep 29 '12 at 13:26
  • 1
    I thought that your trick of using `lst1*1` was really nice...but, sadly, rough profiling suggests that it is at least twice as slow as `lst1[:]`, which is slightly faster than `copy(last1)`. – Andrew Jul 12 '16 at 20:21
14

You can also do:

a = [1, 2, 3]
b = list(a)
Martin Cote
  • 27,586
  • 13
  • 74
  • 99
  • 2
    Is the result a shallow or deep copy? – minty Oct 09 '08 at 18:49
  • 9
    No, using list() is definitely a shallow copy. Try it out. – Christian Oudard Sep 02 '09 at 13:03
  • 3
    Is there a speed difference? Arguably when you do `[:]`, the library is smart enough to know that a copy is being made and thus it could potentially invoke some native C code to do so. With `list(iterable)` does it know/care that the iterable is already materialized and thus can be copied efficiently? – Hamish Grubijan Nov 08 '12 at 22:27
  • So, is the only way to get a deepcopy of a list by using the copy module? Seems strange that Python doesn't include deep copy in its standard functionality. – Shuklaswag Jan 13 '18 at 15:57
7

I like to do:

lst2 = list(lst1)

The advantage over lst1[:] is that the same idiom works for dicts:

dct2 = dict(dct1)
John Fouhy
  • 39,311
  • 19
  • 61
  • 77
  • There was actually a pretty long discussion about the dictionary copy versus list copy on the Python 3K mailing list: http://mail.python.org/pipermail/python-3000/2008-February/thread.html#12052 – Mark Roddy Oct 09 '08 at 16:31
  • The bit of info here is that for dictionaries, you can do d = d.copy() – Christian Oudard Sep 02 '09 at 13:04
3

Short lists, [:] is the best:

In [1]: l = range(10)

In [2]: %timeit list(l)
1000000 loops, best of 3: 477 ns per loop

In [3]: %timeit l[:]
1000000 loops, best of 3: 236 ns per loop

In [6]: %timeit copy(l)
1000000 loops, best of 3: 1.43 us per loop

For larger lists, they're all about the same:

In [7]: l = range(50000)

In [8]: %timeit list(l)
1000 loops, best of 3: 261 us per loop

In [9]: %timeit l[:]
1000 loops, best of 3: 261 us per loop

In [10]: %timeit copy(l)
1000 loops, best of 3: 248 us per loop

For very large lists (I tried 50MM), they're still about the same.

shakefu
  • 93
  • 4
  • I wouldn't bother if I have to do a single copy in between 100s of lines of code. Only if it is a core part of the application and list copy is frequent, I might bother. – Saurabh Jun 11 '13 at 06:13
2

You can also do this:

import copy
list2 = copy.copy(list1)

This should do the same thing as Mark Roddy's shallow copy.

Jason Baker
  • 182,027
  • 130
  • 359
  • 509
2

In terms of performance, there is some overhead to calling list() versus slicing. So for short lists, lst2 = lst1[:] is about twice as fast as lst2 = list(lst1).

In most cases, this is probably outweighed by the fact that list() is more readable, but in tight loops this can be a valuable optimization.

DNS
  • 35,783
  • 18
  • 87
  • 126