Python prevent copying object as reference

Is it possible to copy an object in Python without copying a reference?

For example, if I define a class

class SomeClass: def __init__(self): self.value = 0

and then create an instance

someObject = SomeClass()
someObject.value = 12

and I try to copy it to another instance:

anotherObject = someObject

and try to modify a property,

anotherObject.value = 10

the original property gets modified:

print someObject.value #prints 10

Is there any way to prevent this from happening? To clarify, I want the anotherObject.value to contain 10, but I want someObject.value to still contain the original 12. Is this possible in python?

Thanks in advance.

5 Answers

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)
1
import copy
obj2 = copy.deepcopy(obj2)
1

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.

6
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)
1

You can use copy for that. Try the following:

someObject = SomeClass()
someObject.value = 12
anotherObject = copy.copy(someObject)
anotherObject.value = 10

Now someObject.value will still be 12. You will have to place import copy at the top of your script though.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like