<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>copy – Duplicate objects — Python Module of the Week</title> <link rel="stylesheet" href="../_static/sphinxdoc.css" type="text/css" /> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> <script type="text/javascript"> var DOCUMENTATION_OPTIONS = { URL_ROOT: '../', VERSION: '1.132', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true }; </script> <script type="text/javascript" src="../_static/jquery.js"></script> <script type="text/javascript" src="../_static/underscore.js"></script> <script type="text/javascript" src="../_static/doctools.js"></script> <link rel="author" title="About these documents" href="../about.html" /> <link rel="top" title="Python Module of the Week" href="../index.html" /> <link rel="up" title="Data Types" href="../data_types.html" /> <link rel="next" title="pprint – Pretty-print data structures" href="../pprint/index.html" /> <link rel="prev" title="weakref – Garbage-collectable references to objects" href="../weakref/index.html" /> </head> <body> <div class="related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="../genindex.html" title="General Index" accesskey="I">index</a></li> <li class="right" > <a href="../py-modindex.html" title="Python Module Index" >modules</a> |</li> <li class="right" > <a href="../pprint/index.html" title="pprint – Pretty-print data structures" accesskey="N">next</a> |</li> <li class="right" > <a href="../weakref/index.html" title="weakref – Garbage-collectable references to objects" accesskey="P">previous</a> |</li> <li><a href="../contents.html">PyMOTW</a> »</li> <li><a href="../data_types.html" accesskey="U">Data Types</a> »</li> </ul> </div> <div class="sphinxsidebar"> <div class="sphinxsidebarwrapper"> <h3><a href="../contents.html">Table Of Contents</a></h3> <ul> <li><a class="reference internal" href="#">copy – Duplicate objects</a><ul> <li><a class="reference internal" href="#shallow-copies">Shallow Copies</a></li> <li><a class="reference internal" href="#deep-copies">Deep Copies</a></li> <li><a class="reference internal" href="#controlling-copy-behavior">Controlling Copy Behavior</a></li> <li><a class="reference internal" href="#recursion-in-deep-copy">Recursion in Deep Copy</a></li> </ul> </li> </ul> <h4>Previous topic</h4> <p class="topless"><a href="../weakref/index.html" title="previous chapter">weakref – Garbage-collectable references to objects</a></p> <h4>Next topic</h4> <p class="topless"><a href="../pprint/index.html" title="next chapter">pprint – Pretty-print data structures</a></p> <h3>This Page</h3> <ul class="this-page-menu"> <li><a href="../_sources/copy/index.txt" rel="nofollow">Show Source</a></li> </ul> <div id="searchbox" style="display: none"> <h3>Quick search</h3> <form class="search" action="../search.html" method="get"> <input type="text" name="q" size="18" /> <input type="submit" value="Go" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> <p class="searchtip" style="font-size: 90%"> Enter search terms or a module, class or function name. </p> </div> <script type="text/javascript">$('#searchbox').show(0);</script> </div> </div> <div class="document"> <div class="documentwrapper"> <div class="bodywrapper"> <div class="body"> <div class="section" id="module-copy"> <span id="copy-duplicate-objects"></span><h1>copy – Duplicate objects<a class="headerlink" href="#module-copy" title="Permalink to this headline">¶</a></h1> <table class="docutils field-list" frame="void" rules="none"> <col class="field-name" /> <col class="field-body" /> <tbody valign="top"> <tr class="field"><th class="field-name">Purpose:</th><td class="field-body">Provides functions for duplicating objects using shallow or deep copy semantics.</td> </tr> <tr class="field"><th class="field-name">Python Version:</th><td class="field-body">1.4</td> </tr> </tbody> </table> <p>The copy module includes 2 functions, copy() and deepcopy(), for duplicating existing objects.</p> <div class="section" id="shallow-copies"> <h2>Shallow Copies<a class="headerlink" href="#shallow-copies" title="Permalink to this headline">¶</a></h2> <p>The shallow copy created by copy() is a new container populated with references to the contents of the original object. For example, a new list is constructed and the elements of the original list are appended to it.</p> <div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">copy</span> <span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="k">def</span> <span class="nf">__cmp__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span> <span class="k">return</span> <span class="nb">cmp</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">other</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="n">a</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">(</span><span class="s">'a'</span><span class="p">)</span> <span class="n">l</span> <span class="o">=</span> <span class="p">[</span> <span class="n">a</span> <span class="p">]</span> <span class="n">dup</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> <span class="k">print</span> <span class="s">'l :'</span><span class="p">,</span> <span class="n">l</span> <span class="k">print</span> <span class="s">'dup:'</span><span class="p">,</span> <span class="n">dup</span> <span class="k">print</span> <span class="s">'dup is l:'</span><span class="p">,</span> <span class="p">(</span><span class="n">dup</span> <span class="ow">is</span> <span class="n">l</span><span class="p">)</span> <span class="k">print</span> <span class="s">'dup == l:'</span><span class="p">,</span> <span class="p">(</span><span class="n">dup</span> <span class="o">==</span> <span class="n">l</span><span class="p">)</span> <span class="k">print</span> <span class="s">'dup[0] is l[0]:'</span><span class="p">,</span> <span class="p">(</span><span class="n">dup</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">is</span> <span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">print</span> <span class="s">'dup[0] == l[0]:'</span><span class="p">,</span> <span class="p">(</span><span class="n">dup</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> </pre></div> </div> <p>For a shallow copy, the MyClass instance is not duplicated so the reference in the dup list is to the same object that is in the l list.</p> <div class="highlight-python"><pre>$ python copy_shallow.py l : [<__main__.MyClass instance at 0x10046dc68>] dup: [<__main__.MyClass instance at 0x10046dc68>] dup is l: False dup == l: True dup[0] is l[0]: True dup[0] == l[0]: True</pre> </div> </div> <div class="section" id="deep-copies"> <h2>Deep Copies<a class="headerlink" href="#deep-copies" title="Permalink to this headline">¶</a></h2> <p>The deep copy created by deepcopy() is a new container populated with copies of the contents of the original object. For example, a new list is constructed and the elements of the original list are copied, then the copies are appended to the new list.</p> <p>By replacing the call to copy() with deepcopy(), the difference becomes apparent.</p> <div class="highlight-python"><div class="highlight"><pre><span class="n">dup</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> </pre></div> </div> <p>Notice that the first element of the list is no longer the same object reference, but the two objects still evaluate as being equal.</p> <div class="highlight-python"><pre>$ python copy_deep.py l : [<__main__.MyClass instance at 0x10046dc68>] dup: [<__main__.MyClass instance at 0x10046dc20>] dup is l: False dup == l: True dup[0] is l[0]: False dup[0] == l[0]: True</pre> </div> </div> <div class="section" id="controlling-copy-behavior"> <h2>Controlling Copy Behavior<a class="headerlink" href="#controlling-copy-behavior" title="Permalink to this headline">¶</a></h2> <p>It is possible to control how copies are made using the __copy__ and __deepcopy__ hooks.</p> <ul class="simple"> <li>__copy__() is called without any arguments and should return a shallow copy of the object.</li> <li>__deepcopy__() is called with a memo dictionary, and should return a deep copy of the object. Any member attributes that need to be deep-copied should be passed to copy.deepcopy(), along with the memo dictionary, to control for recursion (see below).</li> </ul> <p>This example illustrates how the methods are called:</p> <div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">copy</span> <span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="k">def</span> <span class="nf">__cmp__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span> <span class="k">return</span> <span class="nb">cmp</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">other</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__copy__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">print</span> <span class="s">'__copy__()'</span> <span class="k">return</span> <span class="n">MyClass</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__deepcopy__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">memo</span><span class="p">):</span> <span class="k">print</span> <span class="s">'__deepcopy__(</span><span class="si">%s</span><span class="s">)'</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">memo</span><span class="p">)</span> <span class="k">return</span> <span class="n">MyClass</span><span class="p">(</span><span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">memo</span><span class="p">))</span> <span class="n">a</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">(</span><span class="s">'a'</span><span class="p">)</span> <span class="n">sc</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="n">dc</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> </pre></div> </div> <div class="highlight-python"><pre>$ python copy_hooks.py __copy__() __deepcopy__({})</pre> </div> </div> <div class="section" id="recursion-in-deep-copy"> <h2>Recursion in Deep Copy<a class="headerlink" href="#recursion-in-deep-copy" title="Permalink to this headline">¶</a></h2> <p>To avoid problems with duplicating recursive data structures, <tt class="docutils literal"><span class="pre">deepcopy()</span></tt> uses a dictionary to track objects that have already been copied. This dictionary is passed to the <tt class="docutils literal"><span class="pre">__deepcopy__()</span></tt> method so it can be used there as well.</p> <p>This example shows how an interconnected data structure such as a Digraph might assist with protecting against recursion by implementing a <tt class="docutils literal"><span class="pre">__deepcopy__()</span></tt> method. This particular example is just for illustration purposes, since the default implementation of <tt class="docutils literal"><span class="pre">deepcopy()</span></tt> already handles the recursion cases correctly.</p> <div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">copy</span> <span class="kn">import</span> <span class="nn">pprint</span> <span class="k">class</span> <span class="nc">Graph</span><span class="p">:</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">connections</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="bp">self</span><span class="o">.</span><span class="n">connections</span> <span class="o">=</span> <span class="n">connections</span> <span class="k">def</span> <span class="nf">addConnection</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">connections</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="s">'<Graph(</span><span class="si">%s</span><span class="s">) id=</span><span class="si">%s</span><span class="s">>'</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="nb">id</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span> <span class="k">def</span> <span class="nf">__deepcopy__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">memo</span><span class="p">):</span> <span class="k">print</span> <span class="k">print</span> <span class="nb">repr</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="n">not_there</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">existing</span> <span class="o">=</span> <span class="n">memo</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">not_there</span><span class="p">)</span> <span class="k">if</span> <span class="n">existing</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">not_there</span><span class="p">:</span> <span class="k">print</span> <span class="s">' ALREADY COPIED TO'</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">existing</span><span class="p">)</span> <span class="k">return</span> <span class="n">existing</span> <span class="n">pprint</span><span class="o">.</span><span class="n">pprint</span><span class="p">(</span><span class="n">memo</span><span class="p">,</span> <span class="n">indent</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mi">40</span><span class="p">)</span> <span class="n">dup</span> <span class="o">=</span> <span class="n">Graph</span><span class="p">(</span><span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">memo</span><span class="p">),</span> <span class="p">[])</span> <span class="k">print</span> <span class="s">' COPYING TO'</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">dup</span><span class="p">)</span> <span class="n">memo</span><span class="p">[</span><span class="bp">self</span><span class="p">]</span> <span class="o">=</span> <span class="n">dup</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">connections</span><span class="p">:</span> <span class="n">dup</span><span class="o">.</span><span class="n">addConnection</span><span class="p">(</span><span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">memo</span><span class="p">))</span> <span class="k">return</span> <span class="n">dup</span> <span class="n">root</span> <span class="o">=</span> <span class="n">Graph</span><span class="p">(</span><span class="s">'root'</span><span class="p">,</span> <span class="p">[])</span> <span class="n">a</span> <span class="o">=</span> <span class="n">Graph</span><span class="p">(</span><span class="s">'a'</span><span class="p">,</span> <span class="p">[</span><span class="n">root</span><span class="p">])</span> <span class="n">b</span> <span class="o">=</span> <span class="n">Graph</span><span class="p">(</span><span class="s">'b'</span><span class="p">,</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span> <span class="n">root</span><span class="p">])</span> <span class="n">root</span><span class="o">.</span><span class="n">addConnection</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="n">root</span><span class="o">.</span><span class="n">addConnection</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="n">dup</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">root</span><span class="p">)</span> </pre></div> </div> <p>First, some basic directed graph methods: A graph can be initialized with a name and a list of existing nodes to which it is connected. The addConnection() method is used to set up bi-directional connections. It is also used by the deepcopy operator.</p> <p>The <tt class="docutils literal"><span class="pre">__deepcopy__()</span></tt> method prints messages to show how it is called, and manages the memo dictionary contents as needed. Instead of copying the connection list wholesale, it creates a new list and appends copies of the individual connections to it. That ensures that the memo dictionary is updated as each new node is duplicated, and avoids recursion issues or extra copies of nodes. As before, it returns the copied object when it is done.</p> <p>Next we can set up a graph with a nodes <em>root</em>, <em>a</em>, and <em>b</em>. The graph looks like:</p> <p class="graphviz"> <img src="../_images/graphviz-a88f86ddde8c68806194453171f860b6db5ea298.png" alt="digraph copy_example { "root"; "a" -> "root"; "b" -> "root"; "b" -> "a"; "root" -> "a"; "root" -> "b"; }" /> </p> <p>There are several cycles in the graph, but by handling the recursion with the memo dictionary we can avoid having the traversal cause a stack overflow error. When the <em>root</em> node is copied, we see:</p> <div class="highlight-python"><pre>$ python copy_recursion.py <Graph(root) id=4299647672> { } COPYING TO <Graph(root) id=4299648032> <Graph(a) id=4299647744> { <Graph(root) id=4299647672>: <Graph(root) id=4299648032>, 4298492288: ['root'], 4299554368: 'root'} COPYING TO <Graph(a) id=4299648104> <Graph(root) id=4299647672> ALREADY COPIED TO <Graph(root) id=4299648032> <Graph(b) id=4299647816> { <Graph(root) id=4299647672>: <Graph(root) id=4299648032>, <Graph(a) id=4299647744>: <Graph(a) id=4299648104>, 4297827832: 'a', 4298492288: [ 'root', 'a', <Graph(root) id=4299647672>, <Graph(a) id=4299647744>], 4299554368: 'root', 4299647672: <Graph(root) id=4299648032>, 4299647744: <Graph(a) id=4299648104>} COPYING TO <Graph(b) id=4299648680></pre> </div> <p>The second time the <em>root</em> node is encountered, while the <em>a</em> node is being copied, <tt class="docutils literal"><span class="pre">__deepcopy__</span></tt> detects the recursion and re-uses the existing value from the memo dictionary instead of creating a new object.</p> <div class="admonition-see-also admonition seealso"> <p class="first admonition-title">See also</p> <dl class="last docutils"> <dt><a class="reference external" href="http://docs.python.org/library/copy.html">copy</a></dt> <dd>The standard library documentation for this module.</dd> </dl> </div> </div> </div> </div> </div> </div> <div class="clearer"></div> </div> <div class="related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="../genindex.html" title="General Index" >index</a></li> <li class="right" > <a href="../py-modindex.html" title="Python Module Index" >modules</a> |</li> <li class="right" > <a href="../pprint/index.html" title="pprint – Pretty-print data structures" >next</a> |</li> <li class="right" > <a href="../weakref/index.html" title="weakref – Garbage-collectable references to objects" >previous</a> |</li> <li><a href="../contents.html">PyMOTW</a> »</li> <li><a href="../data_types.html" >Data Types</a> »</li> </ul> </div> <div class="footer"> © Copyright Doug Hellmann. Last updated on Oct 24, 2010. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>. <br/><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" rel="license"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/us/88x31.png"/></a> </div> </body> </html>