*Memos:
- My post explains the shallow and deep copy of a list.
- My post explains the shallow and deep copy of a tuple.
- My post explains the shallow copy of the set with a tuple.
- My post explains the shallow and deep copy of a dictionary.
- My post explains the shallow and deep copy of an iterator.
- My post explains a set and copy.
<A set with an iterator>
A set can have the hashable types of elements like frozenset
, tuple
, iterator
, etc but cannot have the unhashable types of elements like set
, list
, dict
, etc:
<Normal Copy>:
*Memo:
-
A
andB
refer to the same shallow set and deep iterator. -
is
keyword can check ifv1
andv2
refer to the same set or iterator.
# Shallow set
# ↓ ↓
A = {iter(['a'])}
# ↑↑↑↑↑↑↑↑↑↑↑ Deep iterator
B = A
print(A) # {<list_iterator object at 0x000001F95F9C6410>}
print(B) # {<list_iterator object at 0x000001F95F9C6410>}
print(A is B)
# True
v = B.pop()
print(v) # <list_iterator object at 0x000001F95F9C6410>
print(A) # set()
print(B) # set()
<Shallow Copy>:
set.copy() does shallow copy as shown below:
*Memo:
-
A
andB
refer to different shallow sets. -
A
andB
refer to the same deep iterator.
A = {iter(['a'])}
B = A.copy()
print(A) # {<list_iterator object at 0x000001F9606954E0>}
print(B) # {<list_iterator object at 0x000001F9606954E0>}
print(A is B)
# False
v1 = A.pop()
v2 = B.pop()
print(v1) # <list_iterator object at 0x000001F9606954E0>
print(v2) # <list_iterator object at 0x000001F9606954E0>
print(v1 is v2)
# True
print(next(v1)) # a
print(next(v2)) # StopIteration:
The below with copy.copy() which does shallow copy is equivalent to the above:
import copy
A = {iter(['a'])}
B = copy.copy(A)
print(A) # {<list_iterator object at 0x000001F95F9CD510>}
print(B) # {<list_iterator object at 0x000001F95F9CD510>}
print(A is B)
# False
v1 = A.pop()
v2 = B.pop()
print(v1) # <list_iterator object at 0x000001F95F9CD510>
print(v2) # <list_iterator object at 0x000001F95F9CD510>
print(v1 is v2)
# True
print(next(v1)) # a
print(next(v2)) # StopIteration:
The below with set() which does shallow copy is equivalent to the above:
A = {iter(['a'])}
B = set(A)
print(A) # {<list_iterator object at 0x000001F9605E3730>}
print(B) # {<list_iterator object at 0x000001F9605E3730>}
print(A is B)
# False
v1 = A.pop()
v2 = B.pop()
print(v1) # <list_iterator object at 0x000001F9605E3730>
print(v2) # <list_iterator object at 0x000001F9605E3730>
print(v1 is v2)
# True
print(next(v1)) # a
print(next(v2)) # StopIteration:
<Deep Copy>:
copy.deepcopy() does deep copy as shown below:
*Memo:
-
A
andB
refer to the different shallow sets and deep iterators. -
copy.deepcopy()
should be used because it's safe, doing copy deeply whileset.copy()
,copy.copy()
andset()
aren't safe, doing copy shallowly.
from copy import deepcopy
A = {iter(['a'])}
B = deepcopy(A)
print(A) # {<list_iterator object at 0x000001F96065DE40>}
print(B) # {<list_iterator object at 0x000001F960695CC0>}
print(A is B)
# False
v1 = A.pop()
v2 = B.pop()
print(v1) # <list_iterator object at 0x000001F96065DE40>
print(v2) # <list_iterator object at 0x000001F960695CC0>
print(v1 is v2)
# False
print(next(v1)) # a
print(next(v2)) # a
The below with set.copy() and copy() which do shallow copy is equivalent to the above:
import copy
A = {iter(['a'])}
B = A.copy()
print(A) # {<list_iterator object at 0x000001F9604F6410>}
print(B) # {<list_iterator object at 0x000001F9604F6410>}
print(A is B)
# False
v1 = copy.copy(A.pop())
v2 = copy.copy(B.pop())
print(v1) # <list_iterator object at 0x000001F9604F7910>
print(v2) # <list_iterator object at 0x000001F9605E3190>
print(v1 is v2)
# False
print(next(v1)) # a
print(next(v2)) # a
The below with set() and copy.copy() which do shallow copy is equivalent to the above:
import copy
A = {iter(['a'])}
B = set(A)
print(A) # {<list_iterator object at 0x000001F95F9BDF90>}
print(B) # {<list_iterator object at 0x000001F95F9BDF90>}
print(A is B)
# False
v1 = copy.copy(A.pop())
v2 = copy.copy(B.pop())
print(v1) # <list_iterator object at 0x000001F96065DFF0>
print(v2) # <list_iterator object at 0x000001F96065D360>
print(v1 is v2)
# False
print(next(v1)) # a
print(next(v2)) # a
Additionally, the below is the 3D set with a 2D iterator:
import copy
A = {iter([iter(['a'])])}
B = copy.deepcopy(A)
print(A) # {<list_iterator object at 0x0000029DDF277B20>}
print(B) # {<list_iterator object at 0x0000029DE0049210>}
print(A is B)
# False
v1 = A.pop()
v2 = B.pop()
print(v1) # <list_iterator object at 0x0000029DDF277B20>
print(v2) # <list_iterator object at 0x0000029DE0049210>
print(v1 is v2)
# False
v3 = next(v1)
v4 = next(v2)
print(next(v3)) # a
print(next(v4)) # a
print(v3 is v4)
# False