What are the options to clone or copy a list in Python?
Using new_list = my_list
then modifies new_list
every time my_list
changes.
Why is this?
|
With To actually copy the list, you have various possibilities:
Example:
Result:
|
|||||||||||||
|
Felix already provided an excellent answer, but I thought I'd do a speed comparison of the various methods:
So the fastest is list slicing. But be aware that (Here's the script if anyone's interested or wants to raise any issues:)
EDIT: Added new-style, old-style classes and dicts to the benchmarks, and made the python version much faster and added some more methods including list expressions and |
|||||||||
|
I've been told that Python 3.3+ adds
|
||||
|
There are two semantic ways to copy a list. A shallow copy creates a new list of the same objects, a deep copy creates a new list containing equivalent objects. Shallow list copyA shallow copy only copies the list itself, which is a container of references to the objects in the list. If the objects contained themselves are mutable and one is changed, the change will be reflected in both lists. There are different ways to do this in Python 2 and 3. The Python 2 ways will also work in Python 3. Python 2In Python 2, the idiomatic way of making a shallow copy of a list is with a complete slice of the original:
You can also accomplish the same thing by passing the list through the list constructor,
but using the constructor is less efficient:
Python 3In Python 3, lists get the
In Python 3.5:
Making another pointer does not make a copy
The list is just an array of pointers to the contents, so a shallow copy just copies the pointers, and so you have two different lists, but they have the same contents. To make copies of the contents, you need a deep copy. Deep copiesTo make a deep copy of a list, in Python 2 or 3, use
To demonstrate how this allows us to make new sub-lists:
And so we see that the deep copied list is an entirely different list from the original. You could roll your own function - but don't. You're likely to create bugs you otherwise wouldn't have by using the standard library's deepcopy function. Don't use
|
This answer is only for Python 2. I haven't upgraded to Python 3 yet. There are many answers already that tell you how to make a proper copy, but none of them say why your original 'copy' failed. Python doesn't store values in variables; it binds names to objects. Your original assignment took the object referred to by Each element of a list acts like a name, in that each element binds non-exclusively to an object. A shallow copy creates a new list whose elements bind to the same objects as before.
To take your list copy one step further, copy each object that your list refers to, and bind those element copies to a new list.
This is not yet a deep copy, because each element of a list may refer to other objects, just like the list is bound to its elements. To recursively copy every element in the list, and then each other object referred to by each element, and so on: perform a deep copy.
See the documentation for more information about corner cases in copying. |
||||
|
|
|||
|
Python's idiom for doing this is |
|||
|
Use
|
|||
|
All of the other contributors gave great answers, which work when you have a single dimension (leveled) list, however of the methods mentioned so far, only While Edit: New information brought to light
As others have stated, there
Basically what this does is make a representation of
If you then check the contents of each list, for example a 4 by 3 list, Python will return
While this probably isn't the canonical or syntactically correct way to do it, it seems to work well. I haven't tested performance, but I am going to guess that |
|||||||||||||
|
Unlike other languages have variable and value, python has name and object.
means give the list(object) a name "a", the
just gives the same object a new name "b", so whenever you do something with a, the object changes and therefore b changes. The only way to make a really copy of a is to create a new object like other answers have said. You can see more about this here |
||||
|
Python 3.6.0 TimingsHere are the timing results using Python 3.6.0. Keep in mind these times are relative to one another, not absolute. I stuck to only doing shallow copies, and also added some new methods that weren't possible in Python2, such as
We can see the old winner still comes out on top, but not really by a huge amount, considering the increased readability of the Python3 Note that these methods do not output equivalent results for any input other than lists. They all work for sliceable objects, a few work for any iterable, but only Here is the testing code for interested parties (Template from here):
|
||||
|
Another method (that I feel is fairly readable) is to turn it into a string and then switch it back to a list.
|
|||||||||
|
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?