DEV Community

Super Kai (Kazuya Ito)
Super Kai (Kazuya Ito)

Posted on • Edited on

Shallow copy & Deep copy in Python (8)

Buy Me a Coffee

*Memo for shallow and deep copy:

*Memo for others:

  • My post explains an iterator (1).

Different iterators are referred to, shallow-copied and deep-copied.


A 2D iterator is experimented, doing assignment and shallow and deep copy as shown below:

*Memo:

  • A 2D iterator can be shallow-copied and deep-copied.
  • There are an assignment and 2 kinds of copies, shallow copy and deep copy:
    • An assignment is to create the one or more references to the original top level object and (optional) original lower levels' objects, keeping the same values as before.
    • A shallow copy is to create the one or more references to the new top level object and (optional) original lower levels' objects, keeping the same values as before.
    • A deep copy is to create the two or more references to the new top level object and the new lower levels' objects which you desire but at least the new 2nd level objects, keeping the same values as before:
      • A deep copy is the multiple recursions of a shallow copy so a deep copy can be done with multiple shallow copies.
    • Basically, immutable(hashable) objects aren't copied to save memory like str, bytes, int, float, complex, bool and tuple.

<Assignment>:

*Memo:

  • v1 and v2 refer to the same outer and inner iterator.
  • is keyword can check if v1 and v2 refer to the same outer and/or inner iterator.

A 2D iterator is assigned to a variable without copied as shown below:

     #### Outer iterator ###
#    ↓↓↓↓↓↓               ↓↓ 
v1 = iter([iter([0, 1, 2])])
v2 = v1  # ↑↑↑↑↑↑↑↑↑↑↑ Inner iterator

print(v1) # <list_iterator object at 0x0000029DDFFB7D30>
print(v2) # <list_iterator object at 0x0000029DDFFB7D30>

print(v1 is v2)
# True

print(next(v1)) # <list_iterator object at 0x0000029DDEC54E50>
print(next(v2)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode

<Shallow copy>:

*Memo:

  • v1 and v2 refer to different outer iterators and the same inner iterator.

copy.copy() can shallow-copy a 2D iterator as shown below:

import copy

v1 = iter([iter([0, 1, 2])])
v2 = copy.copy(v1)

print(v1) # <list_iterator object at 0x0000029DE015CDC0>
print(v2) # <list_iterator object at 0x0000029DE015F340>

print(v1 is v2)
# False

v1 = next(v1)
v2 = next(v2)

print(v1) # <list_iterator object at 0x0000029DD4BF82E0>
print(v2) # <list_iterator object at 0x0000029DD4BF82E0>

print(v1 is v2)
# True

print(next(v1)) # a
print(next(v2)) # 1
print(next(v1)) # 2
print(next(v2)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode

iter() cannot shallow-copy a 2D iterator as shown below:

v1 = iter([iter([0, 1, 2])])
v2 = iter(v1)

print(v1) # <list_iterator object at 0x00000192769592D0>
print(v2) # <list_iterator object at 0x00000192769592D0>

print(v1 is v2)
# True

print(next(v1)) # <list_iterator object at 0x000001927695B4F0>
print(next(v2)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode

<Deep copy>:

*Memo:

  • v1 and v2 refer to different outer and inner iterators.

copy.deepcopy() can deep-copy a 2D iterator as shown below:

*Memo:

  • copy.deepcopy() should be used because it's safe, deeply copying a 2D iterator while copy.copy() isn't safe, shallowly copying a 2D iterator.
import copy

v1 = iter([iter([0, 1, 2])])
v2 = copy.deepcopy(v1)

print(v1) # <list_iterator object at 0x0000029DDF283E80>
print(v2) # <list_iterator object at 0x0000029DDF282080>

print(v1 is v2)
# False

v1 = next(v1)
v2 = next(v2)

print(v1) # <list_iterator object at 0x0000029DDF279D50>
print(v2) # <list_iterator object at 0x0000029DDF283FA0>

print(v1 is v2)
# False

print(next(v1)) # 0
print(next(v2)) # 0
print(next(v1)) # 1
print(next(v2)) # 1
print(next(v1)) # 2
print(next(v2)) # 2

print(next(v1))
print(next(v2))
# StopIteration:
Enter fullscreen mode Exit fullscreen mode

copy.copy() can deep-copy a 2D iterator, shallow-copying the outer and inner iterator as shown below:

import copy

v1 = iter([iter([0, 1, 2])])
v2 = copy.copy(v1)

print(v1) # <list_iterator object at 0x0000029DDFF4D7E0>
print(v2) # <list_iterator object at 0x0000029DDFF4D2D0>

print(v1 is v2)
# False

v1 = copy.copy(next(v1))
v2 = copy.copy(next(v2))

print(v1) # <list_iterator object at 0x0000029DDFF4CEE0>
print(v2) # <list_iterator object at 0x0000029DDF283E80>

print(v1 is v2)
# False

print(next(v1)) # 0
print(next(v2)) # 0
print(next(v1)) # 1
print(next(v2)) # 1
print(next(v1)) # 2
print(next(v2)) # 2

print(next(v1))
print(next(v2))
# StopIteration:
Enter fullscreen mode Exit fullscreen mode

Additionally, deepcopy() can deep-copy a 3D iterator as shown below:

import copy

v1 = iter([iter([iter([0, 1, 2])])])
v2 = copy.deepcopy(v1)

print(v1) # <list_iterator object at 0x0000029DDF281EA0>
print(v2) # <list_iterator object at 0x0000029DDEAECB20>

print(v1 is v2)
# False

v1 = next(v1)
v2 = next(v2)

print(v1) # <list_iterator object at 0x0000029DDF282FE0>
print(v2) # <list_iterator object at 0x0000029DDFF4F760>

print(v1 is v2)
# False

v1 = next(v1)
v2 = next(v2)

print(v1) # <list_iterator object at 0x0000029DDEECEA40>
print(v2) # <list_iterator object at 0x0000029DDFF4FAC0>

print(v1 is v2)
# False

print(next(v1)) # 0
print(next(v2)) # 0
print(next(v1)) # 1
print(next(v2)) # 1
print(next(v1)) # 2
print(next(v2)) # 2

print(next(v1))
print(next(v2))
# StopIteration:
Enter fullscreen mode Exit fullscreen mode

Top comments (0)