Deep copy of a dict in 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
>>>
Understanding dict.copy() - shallow or deep?
By "shallow copying" it means the content of the dictionary is not copied by value, but just creating a new reference.
>>> a = {1: [1,2,3]}
>>> b = a.copy()
>>> a, b
({1: [1, 2, 3]}, {1: [1, 2, 3]})
>>> a[1].append(4)
>>> a, b
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
In contrast, a deep copy will copy all contents by value.
>>> import copy
>>> c = copy.deepcopy(a)
>>> a, c
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
>>> a[1].append(5)
>>> a, c
({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})
So:
b = a
: Reference assignment, Makea
andb
points to the same object.b = a.copy()
: Shallow copying,a
andb
will become two isolated objects, but their contents still share the same referenceb = copy.deepcopy(a)
: Deep copying,a
andb
's structure and content become completely isolated.
How to deep copy duplicate a list of dictionaries?
You could use the multiplication approach with dict.copy()
assuming that your dicts are shallow like the ones in your example.
l = [{'k1': 'v1'}, {'k2': 'v2'}]
result = [d.copy() for d in l * 2]
result[0]['k1'] = 'changed'
print(result)
# [{'k1': 'changed'}, {'k2': 'v2'}, {'k1': 'v1'}, {'k2': 'v2'}]
Best way to partially deep copy a dictionary in Python?
Make a "1 level deep" copy of the dict by copying the keys and making copies of the sets. Replace this:
dict_class_copy = deepcopy(dict_class)
with this:
dict_class_copy = {k:set(v) for k,v in dict_class.items()}
and your tests pass.
Nested dictionaries copy() or deepcopy()?
When you're working with a mutable collection like a dictionary or a list, and you perform an assignment, you are not creating a copy of that object by default – i.e., the assignment of some dict b
to another dict a
creates a reference from b
to the original object a
, such that when you mutate b
you indirectly also mutate a
.
See this basic example:
>>> orig = {"a": 1, "b": 2}
>>> new = orig
>>> new["a"] = 9
>>> orig
{'a': 9, 'b': 2}
>>> new
{'a': 9, 'b': 2}
>>> new is orig
True
To fix this and keep the new
and orig
dictionaries separate objects that do not reference each other, make a deepcopy of orig
when assigning it to new
:
>>> import copy
>>> orig = {"a": 1, "b": 2}
>>> new = copy.deepcopy(orig)
>>> new["a"] = 9
>>> orig
{'a': 1, 'b': 2}
>>> new
{'a': 9, 'b': 2}
>>> new is orig
False
Also, here's a tl;dr for the Python documentation linked to above:
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.
On creating new dictionaries in python: Using for_loops vs using deepcopy()
Deep copy is functionally different from using a for loop, which gives a shallow copy. If a dictionary contains any mutable objects, for example, lists, as values, then changing an element in a list changes the corresponding element in a shallow copy, but not in deep:
dic = {'1': [0, 1]}
shallow_copy = dic.copy()
from copy import deepcopy
deep_copy = deepcopy(dic)
dic['1'][0] = 1
shallow_copy
> {'1': [1, 1]}
deep_copy
> {'1': [0, 1]}
(Creating a copy dict via cycle gives essentially the same as dic.copy()) Of course, deep copy is generally slower, because it needs to copy all the elements at all levels of nesting, but in some cases you really want that change of a mutable element in the initial dict doesn't affect the copy - then use deepcopy. If all the values in the dict are immutable, there is no difference.
UPD: (Seeing your comments) Note that strings are immutable in Python.
How to clone / deepcopy Python 3.x dict with internal references to the objects
The correct way to clone custom data structures in Python is to implement the __deepcopy__
special method. This is what is called by the copy.deepcopy
function.
As explained in the doc:
Two problems often exist with deep copy operations that don’t exist
with shallow copy operations:
- Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
- Because deep copy copies everything it may copy too much, such as data which is intended to be shared between copies. [This is the problem you are facing]
The
deepcopy()
function avoids these problems by:
- keeping a “memo” dictionary of objects already copied during the current copying pass; and
- letting user-defined classes override the copying operation or the set of components copied.
Code
import copy
class A:
def __deepcopy__(self, memo):
return self.__class__()
class B:
def __init__(self, ref):
self.ref = ref
def __deepcopy__(self, memo):
return self.__class__(
ref=copy.deepcopy(self.ref, memo)
)
class Holder(dict):
def __deepcopy__(self, memo):
return self.__class__(
{k: copy.deepcopy(v, memo) for k, v in self.items()}
)
Test
import copy
original = Holder()
original['a'] = A()
original['b'] = B(original['a']) # here we create B object
# with reference to A object
assert original['a'] is original['b'].ref # reference is working
cp = copy.deepcopy(original) # we clone our dict
assert cp['a'] is cp['b'].ref # reference is still working
assert original['a'] is not cp['a']
assert original['b'] is not cp['b']
assert original['b'].ref is not cp['b'].ref
Related Topics
How to Add Placeholder to an Entry in Tkinter
How to Print Variables Without Spaces Between Values
How to Count the Occurrence of a Certain Item in an Ndarray
How to Convert Comma-Delimited String to List in Python
Moving Matplotlib Legend Outside of the Axis Makes It Cutoff by the Figure Box
How to Properly Subclass Dict and Override _Getitem_ & _Setitem_
Difference Between Filter and Filter_By in SQLalchemy
Pandas - Slice Large Dataframe into Chunks
Python Function Attributes - Uses and Abuses
How to Check If Two Segments Intersect
Inverse Dictionary Lookup in Python
How to Make an Exe File from a Python Program
Generate a Random Date Between Two Other Dates
How to Set Max_Retries for Requests.Request