-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPrototype.py
158 lines (133 loc) · 5.54 KB
/
Prototype.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import copy
class SelfReferencingEntity:
def __init__(self):
self.parent = None
def set_parent(self, parent):
self.parent = parent
class SomeComponent:
"""
Python provides its own interface of Prototype via `copy.copy` and
`copy.deepcopy` functions. And any class that wants to implement custom
implementations have to override `__copy__` and `__deepcopy__` member
functions.
"""
def __init__(self, some_int, some_list_of_objects, some_circular_ref):
self.some_int = some_int
self.some_list_of_objects = some_list_of_objects
self.some_circular_ref = some_circular_ref
def __copy__(self):
"""
Create a shallow copy. This method will be called whenever someone calls
`copy.copy` with this object and the returned value is returned as the
new shallow copy.
"""
# First, let's create copies of the nested objects.
some_list_of_objects = copy.copy(self.some_list_of_objects)
some_circular_ref = copy.copy(self.some_circular_ref)
# Then, let's clone the object itself, using the prepared clones of the
# nested objects.
new = self.__class__(
self.some_int, some_list_of_objects, some_circular_ref
)
new.__dict__.update(self.__dict__)
return new
def __deepcopy__(self, memo=None):
"""
Create a deep copy. This method will be called whenever someone calls
`copy.deepcopy` with this object and the returned value is returned as
the new deep copy.
What is the use of the argument `memo`? Memo is the dictionary that is
used by the `deepcopy` library to prevent infinite recursive copies in
instances of circular references. Pass it to all the `deepcopy` calls
you make in the `__deepcopy__` implementation to prevent infinite
recursions.
"""
if memo is None:
memo = {}
# First, let's create copies of the nested objects.
some_list_of_objects = copy.deepcopy(self.some_list_of_objects, memo)
some_circular_ref = copy.deepcopy(self.some_circular_ref, memo)
# Then, let's clone the object itself, using the prepared clones of the
# nested objects.
new = self.__class__(
self.some_int, some_list_of_objects, some_circular_ref
)
new.__dict__ = copy.deepcopy(self.__dict__, memo)
return new
if __name__ == "__main__":
list_of_objects = [1, {1, 2, 3}, [1, 2, 3]]
circular_ref = SelfReferencingEntity()
component = SomeComponent(23, list_of_objects, circular_ref)
circular_ref.set_parent(component)
shallow_copied_component = copy.copy(component)
# Let's change the list in shallow_copied_component and see if it changes in
# component.
shallow_copied_component.some_list_of_objects.append("another object")
if component.some_list_of_objects[-1] == "another object":
print(
"Adding elements to `shallow_copied_component`'s "
"some_list_of_objects adds it to `component`'s "
"some_list_of_objects."
)
else:
print(
"Adding elements to `shallow_copied_component`'s "
"some_list_of_objects doesn't add it to `component`'s "
"some_list_of_objects."
)
# Let's change the set in the list of objects.
component.some_list_of_objects[1].add(4)
if 4 in shallow_copied_component.some_list_of_objects[1]:
print(
"Changing objects in the `component`'s some_list_of_objects "
"changes that object in `shallow_copied_component`'s "
"some_list_of_objects."
)
else:
print(
"Changing objects in the `component`'s some_list_of_objects "
"doesn't change that object in `shallow_copied_component`'s "
"some_list_of_objects."
)
deep_copied_component = copy.deepcopy(component)
# Let's change the list in deep_copied_component and see if it changes in
# component.
deep_copied_component.some_list_of_objects.append("one more object")
if component.some_list_of_objects[-1] == "one more object":
print(
"Adding elements to `deep_copied_component`'s "
"some_list_of_objects adds it to `component`'s "
"some_list_of_objects."
)
else:
print(
"Adding elements to `deep_copied_component`'s "
"some_list_of_objects doesn't add it to `component`'s "
"some_list_of_objects."
)
# Let's change the set in the list of objects.
component.some_list_of_objects[1].add(10)
if 10 in deep_copied_component.some_list_of_objects[1]:
print(
"Changing objects in the `component`'s some_list_of_objects "
"changes that object in `deep_copied_component`'s "
"some_list_of_objects."
)
else:
print(
"Changing objects in the `component`'s some_list_of_objects "
"doesn't change that object in `deep_copied_component`'s "
"some_list_of_objects."
)
print(
f"id(deep_copied_component.some_circular_ref.parent): "
f"{id(deep_copied_component.some_circular_ref.parent)}"
)
print(
f"id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent): "
f"{id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent)}"
)
print(
"^^ This shows that deepcopied objects contain same reference, they "
"are not cloned repeatedly."
)