User Tools

Site Tools


python:shallowdeepcopy

Shallow and Deep Copy explained on lists

25.01.2016 (Python 3.4)

The type of copying becomes relevant when dealing with compound objects (e.g. lists, sublists, class instances).

Making a copy of a list

Assignment method

The newly created list will point to the same memory location

colors1 = ["red", "green"]
colors2 = colors1

Slicing method

The newly created list will point to a different memory location (with an exception for sublists, as further shown):

colors1 = ["red", "green"]
colors3 = colors1[:]

Changing elements of the copied list

What it matters here is how the secondary lists were created, and what's the nature of the changed element (simple or compound).

Changing a simple element

# by assignment, it will propagate the changes to the first list
colors1 = ["red", "green"]
colors2 = colors1
colors2[0] = "brown"
colors1, colors2 # ['brown', 'green'], ['brown', 'green']
 
# by slicing, it will be independent
colors1 = ["red", "green"]
colors3 = colors1[:]
colors3[0] = "yellow" 
colors1, colors3 # ['red', 'green'], ['yellow', 'green']

Changing a compound element

This is a tricky one, because no matter the creation method used, the compound element will be always shared.

numbers1 = [1, 2, [3, 4]]
numbers2 = numbers1
numbers3 = numbers1[:]
 
numbers3[2][0] = 99
numbers1, numbers2, numbers3 # [1, 2, [99, 4]], [1, 2, [99, 4]], [1, 2, [99, 4]]

Replacing the whole list

Replacing the whole list it will create independent objects, not sharing the same memory location anymore.

numbers1 = [1, 2, 3]
numbers2 = numbers1
numbers2 = [4, 5, 6]
numbers1, numbers2 # [1, 2, 3], [4, 5, 6]

Replacing the whole compound element (sublist)

This again is tricky, because it matters based on the creation method. As you probably expect, the assignment will still share the same location, but the slicing method will not.

numbers1 = [1, 2, [3, 4]]
numbers2 = numbers1
numbers3 = numbers1[:]
 
numbers2[2] = [10,20,30] # this will replace also numbers1[2]
numbers1, numbers2, numbers3 # [1, 2, [10, 20, 30]], [1, 2, [10, 20, 30]], [1, 2, [3, 4]]
 
numbers3[2] = [100, 200, 300] # but not this one
numbers1, numbers2, numbers3 # [1, 2, [10, 20, 30]], [1, 2, [10, 20, 30]], [1, 2, [100, 200, 300]]

Avoiding headaches, making a deep copy

Use deepcopy from copy module. Simple as that.

from copy import deepcopy
 
numbers1 = [1, 2, [3, 4]]
numbers2 = deepcopy(numbers1) # now the two lists are completely independent

python/shallowdeepcopy.txt · Last modified: 2016/01/25 09:08 by admin