Create an account


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tut] Python List copy()

#1
Python List copy()

<div><p>Surprisingly, even advanced Python coders don’t know the details of the <code>copy()</code> method of Python lists. Time to change that!</p>
<p><strong>Definition and Usage: The <code>list.copy()</code> method copies all <code>list</code> elements into a new list. The new list is the return value of the method. It’s a shallow copy—you copy only the object references to the list elements and not the objects themselves.</strong></p>
<p>Here’s a short example:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> lst = [1, 2, 3]
>>> lst.copy()
[1, 2, 3]</pre>
<p>In the first line, you create the list <code>lst</code> consisting of three integers. You then create a new list by copying all elements.</p>
<p><strong>Puzzle – Try It Yourself:</strong></p>
<p> <iframe height="700px" width="100%" src="https://repl.it/repls/PlaintiveSoulfulGeneric?lite=true" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> </p>
<p><strong>Syntax</strong>: You can call this method on each list object in Python. Here’s the syntax:</p>
<p><code>list.copy()</code></p>
<p><strong>Arguments:</strong> The method doesn’t take any argument.</p>
<p><strong>Return value:</strong> The method <code>list.clear()</code> returns a <code>list</code> object by copying references to all objects in the original list.</p>
<p><strong>Video:</strong></p>
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio">
<div class="wp-block-embed__wrapper">
<div class="ast-oembed-container"><iframe title="Python List copy()" width="1400" height="788" src="https://www.youtube.com/embed/VhLrz7ivZbc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
</figure>
<h2>Python List Copy Shallow</h2>
<p>Before you can truly understand the <code>copy()</code> method in Python, you must understand the concept of a “shallow copy”.</p>
<p>In <a rel="noreferrer noopener" href="https://blog.finxter.com/object-oriented-programming-terminology-cheat-sheet/" target="_blank">object-oriented</a> languages such as Python, everything is an object. The list is an object and the elements in the list are objects, too. A shallow copy of the list creates a new list object—the copy—but it doesn’t create new list elements but simply copies the references to these objects. </p>
<figure class="wp-block-image size-large"><img src="https://blog.finxter.com/wp-content/uploads/2020/03/copyShallow-1024x576.jpg" alt="" class="wp-image-6844" srcset="https://blog.finxter.com/wp-content/uploads/2020/03/copyShallow-scaled.jpg 1024w, https://blog.finxter.com/wp-content/uplo...00x169.jpg 300w, https://blog.finxter.com/wp-content/uplo...68x432.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
<p>You can see that the list below is only a shallow copy pointing to the same elements as the original list. </p>
<p>In Python, the <code>list.copy()</code> method only produces a shallow copy which has much faster runtime complexity. </p>
<p>Here’s an example showing exact this scenario:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> lst = [6, 7, [1, 2], "hello"]
>>> lst_2 = lst.copy()
>>> lst_2[2].append(42)
>>> lst[2]
[1, 2, 42]</pre>
<p>Changing the third list element of the copied list impacts the third list element of the original list.</p>
<h2>Python List Copy Deep</h2>
<p>Having understood the concept of a shallow copy, it’s now easy to understand the concept of a deep copy. A shallow copy only copies the references of the list elements. A deep copy copies the list elements themselves which can lead to a highly recursive behavior because the list elements may be lists themselves that need to be copied deeply and so on. </p>
<p>Here’s a simple deep copy of the same list as shown previously:</p>
<figure class="wp-block-image size-large"><img src="https://blog.finxter.com/wp-content/uploads/2020/03/copyDeep-1024x576.jpg" alt="" class="wp-image-6845" srcset="https://blog.finxter.com/wp-content/uploads/2020/03/copyDeep-scaled.jpg 1024w, https://blog.finxter.com/wp-content/uplo...00x169.jpg 300w, https://blog.finxter.com/wp-content/uplo...68x432.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
<p>In contrast to the shallow copy, the list <code>[1, 2]</code> is copied separately for the deep copy list. If one changes this nested list in the original list, the change would not be visible at the deep copy. (Because the nested list of the deep copy list is an independent object in memory.)</p>
<p>Note that in a deep copy, the string object must not be copied. Why? Because strings are immutable so you cannot change them (and, thus, there will be no dirty “side effects” seen by other copies of the list pointing to the same object in memory. </p>
<p>To get a deep copy in Python, use the <a href="https://docs.python.org/2/library/copy.html" target="_blank" rel="noreferrer noopener">copy module</a> and use the <code>deepcopy()</code> method:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> import copy
>>> lst = [6, 7, [1, 2], "hello"]
>>> lst_2 = copy.deepcopy(lst)
>>> lst_2[2].append(42)
>>> lst[2]
[1, 2]</pre>
<h2>How to Copy a Python List (Alternatives)?</h2>
<p>Say, you want to copy the <code>list</code>. What options are there?</p>
<figure class="wp-block-table is-style-stripes">
<table>
<thead>
<tr>
<th>Method</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>list.copy()</code></td>
<td>Returns a shallow copy of the <code>list</code>.</td>
</tr>
<tr>
<td><code>import copy<br />copy.deepcopy(list)</code></td>
<td>Import the <code>copy</code> module and uses its method to create a deep copy of <code>list</code>. </td>
</tr>
<tr>
<td><code>list[:]</code></td>
<td>Use slicing with default indices to create a shallow copy of the <code>list</code>.</td>
</tr>
<tr>
<td><code>list(x)</code></td>
<td>use the built-in list constructor <code>list(...)</code> to create a shallow copy of the list <code>x</code>. </td>
</tr>
<tr>
<td><code>[el for el in lst]</code></td>
<td>Use <a rel="noreferrer noopener" href="https://blog.finxter.com/list-comprehension/" target="_blank">list comprehension</a> to create a shallow copy of the original list <code>lst</code>. </td>
</tr>
</tbody>
</table>
</figure>
<p>Slicing belongs to the fastest methods (very dirty benchmark <a rel="noreferrer noopener" href="https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list" target="_blank">here</a>). If you need to refresh your Python slicing skills, here’s a tutorial on the Finxter blog:</p>
<p><strong>Related Articles:</strong></p>
<ul>
<li><a href="https://blog.finxter.com/introduction-to-slicing-in-python/" target="_blank" rel="noreferrer noopener">Introduction to Slicing in Python</a></li>
</ul>
<h2>Python List Copy Not Working</h2>
<p>The main reason why the <code>list.copy()</code> method may not work for you is because you assume that it creates a deep copy when, in reality, it only creates a shallow copy of the list. To create a deep copy where the list elements themselves are copied (e.g. for multi-dimensional lists), simply import the <code>copy</code> module and use its method <code>deepcopy(x)</code> to copy list <code>x</code>. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> import copy
>>> lst = [[1, 2], 3, 4]
>>> lst_2 = copy.deepcopy(lst)</pre>
<h2>Python List Copy And Append</h2>
<p>How to copy a list and append an element in one line of Python code?</p>
<p>Simply use slicing to copy the list and the <a rel="noreferrer noopener" href="https://blog.finxter.com/concatenate-lists-in-python/" target="_blank">list concatenation</a> operator <code>+</code> to add the list of a single element <code>[x]</code> to the result. But there are other nice ways, too. Check out the following ways to append element <code>x</code> to a given list <code>lst</code> and return the result as a copy:</p>
<ul>
<li>lst[:] + [x]</li>
<li>lst.copy() + [x]</li>
<li>[*lst, x] </li>
</ul>
<p>The third way to copy a list and append a new element is my personal favorite because it’s fast, easy-to-read, and concise. It uses the <a href="https://blog.finxter.com/what-is-asterisk-in-python/" target="_blank" rel="noreferrer noopener">asterisk operator</a> to unpack the elements of the original list into a new list.</p>
<h2>Python List Copy By Value</h2>
<p>Do you want to copy all elements in your list “by value”? In other words, you want not only the list object to be copied (shallow copy) but also the list elements (deep copy). </p>
<p>This can be done with the <code>deepcopy()</code> method of Python’s <code>copy</code> library. Here’s an example:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> import copy
>>> lst = [6, 7, [1, 2], "hello"]
>>> lst_2 = copy.deepcopy(lst)
>>> lst_2[2].append(42)
>>> lst[2]
[1, 2]</pre>
<p>The element 42 was not appended to the nested list of <code>lst</code>. </p>
<h2>Python List Copy With Slice</h2>
<p>You can simply copy a list <code>lst</code> by using the slice operation <code>lst[:]</code> with default start and stop indices so that all elements are copied in the list. This creates a shallow copy of the list <code>lst</code>. </p>
<p><strong>Related Articles:</strong></p>
<ul>
<li><a href="https://blog.finxter.com/introduction-to-slicing-in-python/" target="_blank" rel="noreferrer noopener">Introduction to Slicing in Python</a></li>
</ul>
<h2>Python List Copy Without First Element</h2>
<p>To copy a list without its first element, simply use slicing <code>list[1:]</code>. By setting the start index to 1 all elements with index larger or equal to 1 are copied into the new list. </p>
<p>Here’s an example:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> lst = [1, 2, 3, 4]
>>> lst[1:]
[2, 3, 4]</pre>
<h2>Python List Copy Without Last Element</h2>
<p>To copy a list without its last element, simply use slicing <code>list[:-1]</code>. By setting the start index to -1 (the right-most list element) all elements but the last one are copied into the new list. </p>
<p>Here’s an example:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> lst = [1, 2, 3, 4]
>>> lst[:-1]
[1, 2, 3]</pre>
<h2>Python List Copy Time Complexity</h2>
<p>The time complexity of shallow list copying—examples are <code>list.copy()</code> or slicing <code>list[:]</code>—is linear to the number of elements in the list. For n list elements, the time complexity is O(n). Why? Because Python goes over all elements in the list and adds a copy of the object reference to the new list (copy by reference). </p>
<p>I wrote a quick script to evaluate that the time complexity of copying a list is, in fact, linear in the number of list elements:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import matplotlib.pyplot as plt
import time y = []
for i in [100000 * j for j in range(10)]: lst = list(range(i)) t0 = time.time() lst_2 = lst[:] t1 = time.time() y.append(t1-t0) plt.plot(y)
plt.xlabel("List elements (10**5)")
plt.ylabel("Time (sec)")
plt.show()</pre>
<p>Here’s the result:</p>
<figure class="wp-block-image size-large"><img src="https://blog.finxter.com/wp-content/uploads/2020/03/image-23.png" alt="" class="wp-image-6850" srcset="https://blog.finxter.com/wp-content/uploads/2020/03/image-23.png 742w, https://blog.finxter.com/wp-content/uplo...00x225.png 300w" sizes="(max-width: 742px) 100vw, 742px" /></figure>
<p>The runtime grows linearly in the number of list elements.</p>
<h2>Python List Copy Partially</h2>
<p>How to copy a list partially? To copy only the elements between <code>start </code>index (included) and <code>stop</code> index (excluded), use slicing like this: <code>list[startConfusedtop]</code>. This results in a new list that contains only parts of the list.</p>
<h2>Python List Copy Multi-Dimensional List</h2>
<p>To copy a multi-dimensional list (a list of lists), you need to create a deep copy. You can accomplish this with the copy library’s deepcopy() method as follows:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> import copy
>>> lst = [[1, 2, 3], [4, 5, 6]]
>>> lst_2 = copy.deepcopy(lst)
>>> lst_2
[[1, 2, 3], [4, 5, 6]]</pre>
<p>Now check if the copy is really deep by clearing the first list element in the copy:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">>>> lst_2[0].clear()
>>> lst
[[1, 2, 3], [4, 5, 6]]
>>> lst_2
[[], [4, 5, 6]]</pre>
<p>You can see that the copy was really deep because the first element of the <code>lst</code> was not affected by the <a rel="noreferrer noopener" href="https://blog.finxter.com/python-list-clear/" target="_blank">clear() method</a> that removed all elements for the deep copy <code>lst_2</code>. </p>
<h2>Python List copy() Thread Safe</h2>
<p>Do you have a multiple threads that access your list at the same time? Then you need to be sure that the list operations (such as <code>copy()</code>) are actually <a rel="noreferrer noopener" href="https://en.wikipedia.org/wiki/Thread_safety" target="_blank">thread safe</a>. </p>
<p>In other words: can you call the <code>copy()</code> operation in two threads on the same list at the same time? (And can you be sure that the result is meaningful?)</p>
<p>The answer is yes (if you use the <a href="https://github.com/python/cpython" target="_blank" rel="noreferrer noopener">cPython </a>implementation). The reason is Python’s <a rel="noreferrer noopener" href="https://wiki.python.org/moin/GlobalInterpreterLock" target="_blank">global interpreter lock</a> that ensures that a thread that’s currently working on it’s code will first finish its current basic Python operation as defined by the cPython implementation. Only if it terminates with this operation will the next thread be able to access the computational resource. This is ensured with a sophisticated locking scheme by the cPython implementation. </p>
<p>The only thing you need to know is that each basic operation in the cPython implementation is <a rel="noreferrer noopener" href="https://en.wikipedia.org/wiki/Atomicity_(database_systems)" target="_blank">atomic</a>. It’s executed wholly and at once before any other thread has the chance to run on the same virtual engine. Therefore, there are no race conditions. An example for such a race condition would be the following: the first thread reads a value from the list, the second threads overwrites the value, and the first thread overwrites the value again invalidating the second thread’s operation.</p>
<p><strong>All cPython operations are thread-safe. </strong>But if you combine those operations into higher-level functions, those are not generally thread safe as they consist of many (possibly interleaving) operations.</p>
<h2>Where to Go From Here?</h2>
<p>The <code>list.copy()</code> method creates a shallow copy of the <code>list</code>. The <code>copy.deepcopy(list)</code> method creates a deep copy of the <code>list</code>. </p>
<p>You’ve learned the ins and outs of this important <a rel="noreferrer noopener" href="https://blog.finxter.com/python-list-methods/" target="_blank">Python list method</a>.</p>
<p>If you keep struggling with those basic Python commands and you feel stuck in your learning progress, I’ve got something for you: <a rel="noreferrer noopener" href="https://www.amazon.com/gp/product/B07ZY7XMX8" target="_blank">Python One-Liners</a> (Amazon Link). </p>
<p>In the book, I’ll give you a thorough overview of critical computer science topics such as machine learning, regular expression, data science, NumPy, and Python basics—all in a single line of Python code!</p>
<p><a rel="noreferrer noopener" href="https://www.amazon.com/gp/product/B07ZY7XMX8" target="_blank">Get the book from Amazon!</a></p>
<p><strong>OFFICIAL BOOK DESCRIPTION:</strong> <em>Python One-Liners will show readers how to perform useful tasks with one line of Python code. Following a brief Python refresher, the book covers essential advanced topics like slicing, list comprehension, broadcasting, lambda functions, algorithms, regular expressions, neural networks, logistic regression and more. Each of the 50 book sections introduces a problem to solve, walks the reader through the skills necessary to solve that problem, then provides a concise one-liner Python solution with a detailed explanation.</em></p>
</div>


https://www.sickgaming.net/blog/2020/03/...list-copy/
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

Forum software by © MyBB Theme © iAndrew 2016