67

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
  • 369,085
  • 72
  • 557
  • 602
sheats
  • 33,062
  • 15
  • 45
  • 44

7 Answers7

107

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
  • 27,122
  • 19
  • 67
  • 71
  • 2
    What do you mean by elements aren't copied? – sheats Oct 08 '08 at 20:16
  • 6
    If the elements are mutable objects they are passed by reference, you have to use deepcopy to really copy them. – Andrea Ambu Oct 08 '08 at 20:20
  • 2
    It will only copy references that are held by the list. If an element in the list holds a reference to another object, that won't be copied. 9 times out of 10 you just need the shallow copy. – Jason Baker Oct 08 '08 at 20:22
  • @sheats see http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy – David Locke Oct 08 '08 at 21:08
  • note: made the mistake of confusing lst2=lst1 as a shallow copy, it's just a ref. – Aram Kocharyan Sep 29 '12 at 13:40
  • 3
    A clearer approach would be: `lst2 = list (lst1)` – CᴴᴀZ May 15 '16 at 15:29
  • @CᴴᴀZ of all the mentioned methods including the one mentioned by you which is the best, I mean in terms of optimization of code.. – Eswar Sep 18 '18 at 08:07
  • I am quite comfortable with the syntax of the first approach, and it's a little dogmatic, but I think it's a little clearer / more explicit to do, rather than `list2 = list1[:]`, instead: `list2 = list1.copy()` – Brian Peterson Mar 30 '23 at 00:52
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
  • 38,188
  • 14
  • 54
  • 77
  • 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
  • 28,864
  • 15
  • 75
  • 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
  • 41,203
  • 19
  • 62
  • 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
  • 192,085
  • 135
  • 376
  • 510
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
  • 37,249
  • 18
  • 95
  • 132