Deep copy of a dict in python

PythonPython 3.x

Python Problem Overview


I would like to make a deep copy of a dict in python. Unfortunately the .deepcopy() method doesn't exist for the dict. How do I do that?

>>> my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}
>>> my_copy = my_dict.deepcopy()
Traceback (most recent calll last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'deepcopy'
>>> my_copy = my_dict.copy()
>>> my_dict['a'][2] = 7
>>> my_copy['a'][2]
7

The last line should be 3.

I would like that modifications in my_dict don't impact the snapshot my_copy.

How do I do that? The solution should be compatible with Python 3.x.

Python Solutions


Solution 1 - Python

How about:

import copy
d = { ... }
d2 = copy.deepcopy(d)

Python 2 or 3:

Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import copy
>>> my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}
>>> my_copy = copy.deepcopy(my_dict)
>>> my_dict['a'][2] = 7
>>> my_copy['a'][2]
3
>>>

Solution 2 - Python

dict.copy() is a shallow copy function for dictionary
id is built-in function that gives you the address of variable

First you need to understand "why is this particular problem is happening?"

In [1]: my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}

In [2]: my_copy = my_dict.copy()

In [3]: id(my_dict)
Out[3]: 140190444167808

In [4]: id(my_copy)
Out[4]: 140190444170328

In [5]: id(my_copy['a'])
Out[5]: 140190444024104

In [6]: id(my_dict['a'])
Out[6]: 140190444024104

The address of the list present in both the dicts for key 'a' is pointing to same location.
Therefore when you change value of the list in my_dict, the list in my_copy changes as well.


Solution for data structure mentioned in the question:

In [7]: my_copy = {key: value[:] for key, value in my_dict.items()}

In [8]: id(my_copy['a'])
Out[8]: 140190444024176

Or you can use deepcopy as mentioned above.

Solution 3 - Python

Python 3.x

from copy import deepcopy

my_dict = {'one': 1, 'two': 2}
new_dict_deepcopy = deepcopy(my_dict)

Without deepcopy, I am unable to remove the hostname dictionary from within my domain dictionary.

Without deepcopy I get the following error:

"RuntimeError: dictionary changed size during iteration"

...when I try to remove the desired element from my dictionary inside of another dictionary.

import socket
import xml.etree.ElementTree as ET
from copy import deepcopy

domain is a dictionary object

def remove_hostname(domain, hostname):
    domain_copy = deepcopy(domain)
    for domains, hosts in domain_copy.items():
        for host, port in hosts.items():
           if host == hostname:
                del domain[domains][host]
    return domain

Example output: [orginal]domains = {'localdomain': {'localhost': {'all': '4000'}}}

[new]domains = {'localdomain': {} }}

So what's going on here is I am iterating over a copy of a dictionary rather than iterating over the dictionary itself. With this method, you are able to remove elements as needed.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOlivier Gr&#233;goireView Question on Stackoverflow
Solution 1 - PythonLasse V. KarlsenView Answer on Stackoverflow
Solution 2 - PythontheBuzzyCoderView Answer on Stackoverflow
Solution 3 - PythonxprosView Answer on Stackoverflow