Tuesday, March 1, 2011

What is the best way to copy a list in Python?

lst1 = ['one', 2, 3]

// What is the best way of the following  -- or is there another way?
lst2 = list(lst1)
lst2 = lst1[:]

import copy
lst2 = copy.copy(lst1)
From stackoverflow
  • 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)
    
    sheats : What do you mean by elements aren't copied?
    Andrea Ambu : If the elements are mutable objects they are passed by reference, you have to use deepcopy to really copy them.
    Jason Baker : 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.
    David Locke : @sheats see http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy
  • 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]]
    

    In this case it works with copy too, because there is only one deeper level, but if you have list of lists of list of... or other objects (i took lists just for simplicity) you need deepcopy.

  • You can also do this:

    import copy
    list2 = copy.copy(list1)
    

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

  • You can also do:

    a = [1, 2, 3]
    b = list(a)
    
    minty : Is the result a shallow or deep copy?
    Martin Cote : That would be a deep copy.
    Christian Oudard : No, using list() is definitely a shallow copy. Try it out.
  • I like to do:

    lst2 = list(lst1)
    

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

    dct2 = dict(dct1)
    
    Mark Roddy : 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
    Christian Oudard : The bit of info here is that for dictionaries, you can do d = d.copy()

0 comments:

Post a Comment