Difference Between Shallow Copy, Deepcopy and Normal Assignment Operation

What is the difference between shallow copy, deepcopy and normal assignment operation?

Normal assignment operations will simply point the new variable towards the existing object. The docs explain the difference between shallow and deep copies:

The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.

  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the
    original.

Here's a little demonstration:

import copy

a = [1, 2, 3]
b = [4, 5, 6]
c = [a, b]

Using normal assignment operatings to copy:

d = c

print id(c) == id(d) # True - d is the same object as c
print id(c[0]) == id(d[0]) # True - d[0] is the same object as c[0]

Using a shallow copy:

d = copy.copy(c)

print id(c) == id(d) # False - d is now a new object
print id(c[0]) == id(d[0]) # True - d[0] is the same object as c[0]

Using a deep copy:

d = copy.deepcopy(c)

print id(c) == id(d) # False - d is now a new object
print id(c[0]) == id(d[0]) # False - d[0] is now a new object

What is the difference between a deep copy and a shallow copy?

Shallow copies duplicate as little as possible. A shallow copy of a collection is a copy of the collection structure, not the elements. With a shallow copy, two collections now share the individual elements.

Deep copies duplicate everything. A deep copy of a collection is two collections with all of the elements in the original collection duplicated.

Mutable and Inmutable Deep/Shallow copies Python

TL;DR

  • Shallow copy makes a copy of the outer level items in the list, whatever nested inside those items will still be copied by reference
  • Deep copy goes through all nested items and copies each single one of them

Your example doesn't include copying, a = b will have both variables point to the same list.

Consider the following examples:

a = [[1, 2, 3], [4, 5, 6]]
b = copy.copy(a) # shallow copy, you can use b = list(a) too
a[0][0] = 5
# b[0][0] will be 5

a[0] = [0, 0]
# b[0] will not change

Why? Because shallow copy produces a copy of the elements in the list in the first level (b[0] is a copy of a[0]) but if a[0] is a list, anything inside that list is pointing to the same place as the elements in b[0].

While deep copy keeps going and copying all the elements no matter how nested the elements are

a = [[1, 2, 3], [4, 5, 6]]
b = copy.deepcopy(a) # deep copy
a[0][0] = 5
# b[0][0] will not change

a[0] = [0, 0]
# b[0] will not change

Is copy.copy different from assignment in python

All python variables are bindings to some objects in memory.

  1. Does this code do anything?

Yes, it does.
Actually it creates a new object in memory with new name.


  1. How does copy.copy(node) differ from node = node?

By assignment you are getting different names for the same object.
So if you are really need a copy you should use shallow or deep copy.

Example:

>>> x = [1]
>>> id(x)
35964488
>>> y = x
>>> id(y)
35964488
>>> z = x[:]
>>> id(z)
35964768

So x and y have same id, while z has different.

Same here:

>>> import copy
>>> c = copy.copy(x)
>>> id(c)
35985168
>>> id(x)
35964488

Quote from docs about shallow and deep copy:

The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances):

A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in
the original.

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the
original.

Shallow/Deep copy in python

A shallow copy creates a new list object and copies across all the references contained in the source list. A deep copy creates new objects recursively.

You won't see the difference with just immutable contents. Use nested lists to see the difference:

>>> import copy
>>> a = ['foo', 'bar', 'baz']
>>> b = ['spam', 'ham', 'eggs']
>>> outer = [a, b]
>>> copy_of_outer = copy.copy(outer)
>>> outer is copy_of_outer
False
>>> outer == copy_of_outer
True
>>> outer[0] is a
True
>>> copy_of_outer[0] is a
True
>>> outer[0] is copy_of_outer[0]
True

A new copy of the outer list was created, but the contents of the original and the copy are still the same objects.

>>> deep_copy_of_outer = copy.deepcopy(outer)
>>> deep_copy_of_outer[0] is a
False
>>> outer[0] is deep_copy_of_outer[0]
False

The deep copy doesn't share contents with the original; the a list has been recursively copied as well.



Related Topics



Leave a reply



Submit