Python prevent copying object as reference
import copy
obj2 = copy.deepcopy(obj2)
The problem is, with
anotherObject = someObject
you don't copy the object, but just add another reference to it. To copy an object, try this:
from copy import copy
anotherObject = copy(someObject)
As you've noticed, anotherObject = someObject
doesn't make a copy - if you want a copy, try
import copy
otherObject = copy.copy(someObject)
The copy.copy
vs copy.deepcopy
distinction is important here - you can get away with copy.copy
for the simple object you've described, but a more nested object would require copy.deepcopy
.
copy.copy(someObject)
makes a copy only of the object someObject
, but if someObject
contains references to other objects that can be changed ("mutable" objects) as in
someObject.value.this_one_has_values_too = 4
or
someObject.value[0] = 1
or
someObject.value['key'] = 'value'
then references to those objects will be made in the copy. If you use copy.deepcopy
, they'll also be copied over.
A great way to gain an understanding of this is playing with the Online Python Tutor (see linked example) but here's a straightforward demonstration of the behavior without the useful diagraming Online Python Tutor provides.
>>> import copy
>>> class Foo(object):
... pass
...
>>> f = Foo()
>>> f.value = 1
>>> f.nested_value = [2,3,4]
>>> deep = copy.deepcopy(f)
>>> deep.value = 5
>>> f.value
1
>>> deep.nested_value.append(6)
>>> f.nested_value
[2, 3, 4]
>>> shallow = copy.copy(f)
>>> shallow.value = 7
>>> f.value
1
>>> shallow.nested_value.append(8)
>>> f.nested_value
[2, 3, 4, 8]
Edit: But what about the integer in the first example? It's actually being shared between the f
object and the shallow
object, but that's not a problem - it's not editable; we can't change an integer object like 1
to be any different, so we might as well save memory and use that one object anytime any Python object needs a reference to 1.
The thing to read about this is Ned's Facts and Myths about Python names and values.
import copy
In some cases just:
copy_obj = copy.copy(obj)
is enough but in other cases you should use:
copy_obj = copy.deepcopy(obj)