OLD | NEW |
1 """Generic (shallow and deep) copying operations. | 1 """Generic (shallow and deep) copying operations. |
2 | 2 |
3 Interface summary: | 3 Interface summary: |
4 | 4 |
5 import copy | 5 import copy |
6 | 6 |
7 x = copy.copy(y) # make a shallow copy of y | 7 x = copy.copy(y) # make a shallow copy of y |
8 x = copy.deepcopy(y) # make a deep copy of y | 8 x = copy.deepcopy(y) # make a deep copy of y |
9 | 9 |
10 For module specific errors, copy.Error is raised. | 10 For module specific errors, copy.Error is raised. |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 rv = reductor(2) | 166 rv = reductor(2) |
167 else: | 167 else: |
168 reductor = getattr(x, "__reduce__", None) | 168 reductor = getattr(x, "__reduce__", None) |
169 if reductor: | 169 if reductor: |
170 rv = reductor() | 170 rv = reductor() |
171 else: | 171 else: |
172 raise Error( | 172 raise Error( |
173 "un(deep)copyable object of type %s" % cls) | 173 "un(deep)copyable object of type %s" % cls) |
174 y = _reconstruct(x, rv, 1, memo) | 174 y = _reconstruct(x, rv, 1, memo) |
175 | 175 |
176 # If is its own copy, don't memoize. | 176 memo[d] = y |
177 if y is not x: | 177 _keep_alive(x, memo) # Make sure x lives at least as long as d |
178 memo[d] = y | |
179 _keep_alive(x, memo) # Make sure x lives at least as long as d | |
180 return y | 178 return y |
181 | 179 |
182 _deepcopy_dispatch = d = {} | 180 _deepcopy_dispatch = d = {} |
183 | 181 |
184 def _deepcopy_atomic(x, memo): | 182 def _deepcopy_atomic(x, memo): |
185 return x | 183 return x |
186 d[type(None)] = _deepcopy_atomic | 184 d[type(None)] = _deepcopy_atomic |
187 d[type(Ellipsis)] = _deepcopy_atomic | 185 d[type(Ellipsis)] = _deepcopy_atomic |
188 d[int] = _deepcopy_atomic | 186 d[int] = _deepcopy_atomic |
189 d[float] = _deepcopy_atomic | 187 d[float] = _deepcopy_atomic |
(...skipping 19 matching lines...) Expand all Loading... |
209 memo[id(x)] = y | 207 memo[id(x)] = y |
210 for a in x: | 208 for a in x: |
211 y.append(deepcopy(a, memo)) | 209 y.append(deepcopy(a, memo)) |
212 return y | 210 return y |
213 d[list] = _deepcopy_list | 211 d[list] = _deepcopy_list |
214 | 212 |
215 def _deepcopy_tuple(x, memo): | 213 def _deepcopy_tuple(x, memo): |
216 y = [] | 214 y = [] |
217 for a in x: | 215 for a in x: |
218 y.append(deepcopy(a, memo)) | 216 y.append(deepcopy(a, memo)) |
219 # We're not going to put the tuple in the memo, but it's still important we | 217 d = id(x) |
220 # check for it, in case the tuple contains recursive mutable structures. | |
221 try: | 218 try: |
222 return memo[id(x)] | 219 return memo[d] |
223 except KeyError: | 220 except KeyError: |
224 pass | 221 pass |
225 for i in range(len(x)): | 222 for i in range(len(x)): |
226 if x[i] is not y[i]: | 223 if x[i] is not y[i]: |
227 y = tuple(y) | 224 y = tuple(y) |
228 break | 225 break |
229 else: | 226 else: |
230 y = x | 227 y = x |
| 228 memo[d] = y |
231 return y | 229 return y |
232 d[tuple] = _deepcopy_tuple | 230 d[tuple] = _deepcopy_tuple |
233 | 231 |
234 def _deepcopy_dict(x, memo): | 232 def _deepcopy_dict(x, memo): |
235 y = {} | 233 y = {} |
236 memo[id(x)] = y | 234 memo[id(x)] = y |
237 for key, value in x.items(): | 235 for key, value in x.items(): |
238 y[deepcopy(key, memo)] = deepcopy(value, memo) | 236 y[deepcopy(key, memo)] = deepcopy(value, memo) |
239 return y | 237 return y |
240 d[dict] = _deepcopy_dict | 238 d[dict] = _deepcopy_dict |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 dict.__init__(self, d) | 379 dict.__init__(self, d) |
382 def __setitem__(self, k, i): | 380 def __setitem__(self, k, i): |
383 dict.__setitem__(self, k, i) | 381 dict.__setitem__(self, k, i) |
384 self.a | 382 self.a |
385 o = odict({"A" : "B"}) | 383 o = odict({"A" : "B"}) |
386 x = deepcopy(o) | 384 x = deepcopy(o) |
387 print(o, x) | 385 print(o, x) |
388 | 386 |
389 if __name__ == '__main__': | 387 if __name__ == '__main__': |
390 _test() | 388 _test() |
OLD | NEW |