3 Generic (shallow and deep) copying operations.
9 x = copy.copy(y) # make a shallow copy of y
10 x = copy.deepcopy(y) # make a deep copy of y
12 For module specific errors, copy.Error is raised.
14 The difference between shallow and deep copying is only relevant for
15 compound objects (objects that contain other objects, like lists or
18 - A shallow copy constructs a new compound object and then (to the
19 extent possible) inserts *the same objects* into it that the
22 - A deep copy constructs a new compound object and then, recursively,
23 inserts *copies* into it of the objects found in the original.
25 Two problems often exist with deep copy operations that don't exist
26 with shallow copy operations:
28 a) recursive objects (compound objects that, directly or indirectly,
29 contain a reference to themselves) may cause a recursive loop
31 b) because deep copy copies *everything* it may copy too much, e.g.
32 administrative data structures that should be shared even between
35 Python's deep copy operation avoids these problems by:
37 a) keeping a table of objects already copied during the current
40 b) letting user-defined classes override the copying operation or the
41 set of components copied
43 This version does not copy types like module, class, function, method,
44 nor stack trace, stack frame, nor file, socket, window, nor array, nor
47 Classes can use the same interfaces to control copying that they use
48 to control pickling: they can define methods called __getinitargs__(),
49 __getstate__() and __setstate__(). See the documentation for module
50 "pickle" for information on these methods.
54 from copy_reg import dispatch_table
56 class Error(Exception):
58 error = Error # backward compatibility
61 from org.python.core import PyStringMap
65 __all__ = ["Error", "copy", "deepcopy"]
68 """Shallow copy operation on arbitrary Python objects.
70 See the module's __doc__ string for more info.
75 copier = _copy_dispatch.get(cls)
79 copier = getattr(cls, "__copy__", None)
83 reductor = dispatch_table.get(cls)
87 reductor = getattr(x, "__reduce_ex__", None)
91 reductor = getattr(x, "__reduce__", None)
95 raise Error("un(shallow)copyable object of type %s" % cls)
97 return _reconstruct(x, rv, 0)
100 _copy_dispatch = d = {}
102 def _copy_immutable(x):
104 for t in (type(None), int, long, float, bool, str, tuple,
105 frozenset, type, xrange, types.ClassType,
106 types.BuiltinFunctionType,
108 d[t] = _copy_immutable
109 for name in ("ComplexType", "UnicodeType", "CodeType"):
110 t = getattr(types, name, None)
112 d[t] = _copy_immutable
114 def _copy_with_constructor(x):
116 for t in (list, dict, set):
117 d[t] = _copy_with_constructor
119 def _copy_with_copy_method(x):
121 if PyStringMap is not None:
122 d[PyStringMap] = _copy_with_copy_method
125 if hasattr(x, '__copy__'):
127 if hasattr(x, '__getinitargs__'):
128 args = x.__getinitargs__()
129 y = x.__class__(*args)
132 y.__class__ = x.__class__
133 if hasattr(x, '__getstate__'):
134 state = x.__getstate__()
137 if hasattr(y, '__setstate__'):
138 y.__setstate__(state)
140 y.__dict__.update(state)
142 d[types.InstanceType] = _copy_inst
146 def deepcopy(x, memo=None, _nil=[]):
147 """Deep copy operation on arbitrary Python objects.
149 See the module's __doc__ string for more info.
156 y = memo.get(d, _nil)
162 copier = _deepcopy_dispatch.get(cls)
167 issc = issubclass(cls, type)
168 except TypeError: # cls is not a class (old Boost; see SF #502085)
171 y = _deepcopy_atomic(x, memo)
173 copier = getattr(x, "__deepcopy__", None)
177 reductor = dispatch_table.get(cls)
181 reductor = getattr(x, "__reduce_ex__", None)
185 reductor = getattr(x, "__reduce__", None)
190 "un(deep)copyable object of type %s" % cls)
191 y = _reconstruct(x, rv, 1, memo)
194 _keep_alive(x, memo) # Make sure x lives at least as long as d
197 _deepcopy_dispatch = d = {}
199 def _deepcopy_atomic(x, memo):
201 d[type(None)] = _deepcopy_atomic
202 d[int] = _deepcopy_atomic
203 d[long] = _deepcopy_atomic
204 d[float] = _deepcopy_atomic
205 d[bool] = _deepcopy_atomic
207 d[complex] = _deepcopy_atomic
210 d[str] = _deepcopy_atomic
212 d[unicode] = _deepcopy_atomic
216 d[types.CodeType] = _deepcopy_atomic
217 except AttributeError:
219 d[type] = _deepcopy_atomic
220 d[xrange] = _deepcopy_atomic
221 d[types.ClassType] = _deepcopy_atomic
222 d[types.BuiltinFunctionType] = _deepcopy_atomic
223 d[types.FunctionType] = _deepcopy_atomic
225 def _deepcopy_list(x, memo):
229 y.append(deepcopy(a, memo))
231 d[list] = _deepcopy_list
233 def _deepcopy_tuple(x, memo):
236 y.append(deepcopy(a, memo))
242 for i in range(len(x)):
250 d[tuple] = _deepcopy_tuple
252 def _deepcopy_dict(x, memo):
255 for key, value in x.iteritems():
256 y[deepcopy(key, memo)] = deepcopy(value, memo)
258 d[dict] = _deepcopy_dict
259 if PyStringMap is not None:
260 d[PyStringMap] = _deepcopy_dict
262 def _keep_alive(x, memo):
263 """Keeps a reference to the object x in the memo.
265 Because we remember objects by their id, we have
266 to assure that possibly temporary objects are kept
267 alive by referencing them.
268 We store a reference at the id of the memo, which should
269 normally not be used unless someone tries to deepcopy
273 memo[id(memo)].append(x)
275 # aha, this is the first one :-)
278 def _deepcopy_inst(x, memo):
279 if hasattr(x, '__deepcopy__'):
280 return x.__deepcopy__(memo)
281 if hasattr(x, '__getinitargs__'):
282 args = x.__getinitargs__()
283 args = deepcopy(args, memo)
284 y = x.__class__(*args)
287 y.__class__ = x.__class__
289 if hasattr(x, '__getstate__'):
290 state = x.__getstate__()
293 state = deepcopy(state, memo)
294 if hasattr(y, '__setstate__'):
295 y.__setstate__(state)
297 y.__dict__.update(state)
299 d[types.InstanceType] = _deepcopy_inst
301 def _reconstruct(x, info, deep, memo=None):
302 if isinstance(info, str):
304 assert isinstance(info, tuple)
308 assert n in (2, 3, 4, 5)
309 callable, args = info[:2]
323 args = deepcopy(args, memo)
326 if listiter is not None:
327 for item in listiter:
329 item = deepcopy(item, memo)
331 if dictiter is not None:
332 for key, value in dictiter:
334 key = deepcopy(key, memo)
335 value = deepcopy(value, memo)
339 state = deepcopy(state, memo)
340 if hasattr(y, '__setstate__'):
341 y.__setstate__(state)
343 if isinstance(state, tuple) and len(state) == 2:
344 state, slotstate = state
347 if state is not None:
348 y.__dict__.update(state)
349 if slotstate is not None:
350 for key, value in slotstate.iteritems():
351 setattr(y, key, value)
358 # Helper for instance creation without calling __init__
363 l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
364 {'abc': 'ABC'}, (), [], {}]
372 def __init__(self, arg=None):
375 if __name__ == '__main__':
382 def __getstate__(self):
383 return {'a': self.a, 'arg': self.arg}
384 def __setstate__(self, state):
385 for key, value in state.iteritems():
386 setattr(self, key, value)
387 def __deepcopy__(self, memo=None):
388 new = self.__class__(deepcopy(self.arg, memo))
391 c = C('argument sketch')
401 l.append({l[1]: l, 'xyz': l[2]})
404 print map(repr.repr, l)
405 print map(repr.repr, l1)
406 print map(repr.repr, l2)
407 print map(repr.repr, l3)
410 print map(repr.repr, l)
411 print map(repr.repr, l1)
412 print map(repr.repr, l2)
413 print map(repr.repr, l3)
415 if __name__ == '__main__':