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)

Tags:

Python