1 """Generic (shallow and deep) copying operations.
7 x = copy.copy(y) # make a shallow copy of y
8 x = copy.deepcopy(y) # make a deep copy of y
10 For module specific errors, copy.Error is raised.
12 The difference between shallow and deep copying is only relevant for
13 compound objects (objects that contain other objects, like lists or
16 - A shallow copy constructs a new compound object and then (to the
17 extent possible) inserts *the same objects* into it that the
20 - A deep copy constructs a new compound object and then, recursively,
21 inserts *copies* into it of the objects found in the original.
23 Two problems often exist with deep copy operations that don't exist
24 with shallow copy operations:
26 a) recursive objects (compound objects that, directly or indirectly,
27 contain a reference to themselves) may cause a recursive loop
29 b) because deep copy copies *everything* it may copy too much, e.g.
30 administrative data structures that should be shared even between
33 Python's deep copy operation avoids these problems by:
35 a) keeping a table of objects already copied during the current
38 b) letting user-defined classes override the copying operation or the
39 set of components copied
41 This version does not copy types like module, class, function, method,
42 nor stack trace, stack frame, nor file, socket, window, nor array, nor
45 Classes can use the same interfaces to control copying that they use
46 to control pickling: they can define methods called __getinitargs__(),
47 __getstate__() and __setstate__(). See the documentation for module
48 "pickle" for information on these methods.
53 from copy_reg
import dispatch_table
55 class Error(Exception):
57 error
= Error
# backward compatibility
60 from org
.python
.core
import PyStringMap
64 __all__
= ["Error", "copy", "deepcopy"]
67 """Shallow copy operation on arbitrary Python objects.
69 See the module's __doc__ string for more info.
74 copier
= _copy_dispatch
.get(cls
)
78 copier
= getattr(cls
, "__copy__", None)
82 reductor
= dispatch_table
.get(cls
)
86 reductor
= getattr(x
, "__reduce_ex__", None)
90 reductor
= getattr(x
, "__reduce__", None)
94 raise Error("un(shallow)copyable object of type %s" % cls
)
96 return _reconstruct(x
, rv
, 0)
99 _copy_dispatch
= d
= {}
101 def _copy_immutable(x
):
103 for t
in (type(None), int, long, float, bool, str, tuple,
104 frozenset, type, xrange, types
.ClassType
,
105 types
.BuiltinFunctionType
, type(Ellipsis),
106 types
.FunctionType
, weakref
.ref
):
107 d
[t
] = _copy_immutable
108 for name
in ("ComplexType", "UnicodeType", "CodeType"):
109 t
= getattr(types
, name
, None)
111 d
[t
] = _copy_immutable
113 def _copy_with_constructor(x
):
115 for t
in (list, dict, set):
116 d
[t
] = _copy_with_constructor
118 def _copy_with_copy_method(x
):
120 if PyStringMap
is not None:
121 d
[PyStringMap
] = _copy_with_copy_method
124 if hasattr(x
, '__copy__'):
126 if hasattr(x
, '__getinitargs__'):
127 args
= x
.__getinitargs
__()
128 y
= x
.__class
__(*args
)
131 y
.__class
__ = x
.__class
__
132 if hasattr(x
, '__getstate__'):
133 state
= x
.__getstate
__()
136 if hasattr(y
, '__setstate__'):
137 y
.__setstate
__(state
)
139 y
.__dict
__.update(state
)
141 d
[types
.InstanceType
] = _copy_inst
145 def deepcopy(x
, memo
=None, _nil
=[]):
146 """Deep copy operation on arbitrary Python objects.
148 See the module's __doc__ string for more info.
155 y
= memo
.get(d
, _nil
)
161 copier
= _deepcopy_dispatch
.get(cls
)
166 issc
= issubclass(cls
, type)
167 except TypeError: # cls is not a class (old Boost; see SF #502085)
170 y
= _deepcopy_atomic(x
, memo
)
172 copier
= getattr(x
, "__deepcopy__", None)
176 reductor
= dispatch_table
.get(cls
)
180 reductor
= getattr(x
, "__reduce_ex__", None)
184 reductor
= getattr(x
, "__reduce__", None)
189 "un(deep)copyable object of type %s" % cls
)
190 y
= _reconstruct(x
, rv
, 1, memo
)
193 _keep_alive(x
, memo
) # Make sure x lives at least as long as d
196 _deepcopy_dispatch
= d
= {}
198 def _deepcopy_atomic(x
, memo
):
200 d
[type(None)] = _deepcopy_atomic
201 d
[type(Ellipsis)] = _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
224 d
[weakref
.ref
] = _deepcopy_atomic
226 def _deepcopy_list(x
, memo
):
230 y
.append(deepcopy(a
, memo
))
232 d
[list] = _deepcopy_list
234 def _deepcopy_tuple(x
, memo
):
237 y
.append(deepcopy(a
, memo
))
243 for i
in range(len(x
)):
251 d
[tuple] = _deepcopy_tuple
253 def _deepcopy_dict(x
, memo
):
256 for key
, value
in x
.iteritems():
257 y
[deepcopy(key
, memo
)] = deepcopy(value
, memo
)
259 d
[dict] = _deepcopy_dict
260 if PyStringMap
is not None:
261 d
[PyStringMap
] = _deepcopy_dict
263 def _deepcopy_method(x
, memo
): # Copy instance methods
264 return type(x
)(x
.im_func
, deepcopy(x
.im_self
, memo
), x
.im_class
)
265 _deepcopy_dispatch
[types
.MethodType
] = _deepcopy_method
267 def _keep_alive(x
, memo
):
268 """Keeps a reference to the object x in the memo.
270 Because we remember objects by their id, we have
271 to assure that possibly temporary objects are kept
272 alive by referencing them.
273 We store a reference at the id of the memo, which should
274 normally not be used unless someone tries to deepcopy
278 memo
[id(memo
)].append(x
)
280 # aha, this is the first one :-)
283 def _deepcopy_inst(x
, memo
):
284 if hasattr(x
, '__deepcopy__'):
285 return x
.__deepcopy
__(memo
)
286 if hasattr(x
, '__getinitargs__'):
287 args
= x
.__getinitargs
__()
288 args
= deepcopy(args
, memo
)
289 y
= x
.__class
__(*args
)
292 y
.__class
__ = x
.__class
__
294 if hasattr(x
, '__getstate__'):
295 state
= x
.__getstate
__()
298 state
= deepcopy(state
, memo
)
299 if hasattr(y
, '__setstate__'):
300 y
.__setstate
__(state
)
302 y
.__dict
__.update(state
)
304 d
[types
.InstanceType
] = _deepcopy_inst
306 def _reconstruct(x
, info
, deep
, memo
=None):
307 if isinstance(info
, str):
309 assert isinstance(info
, tuple)
313 assert n
in (2, 3, 4, 5)
314 callable, args
= info
[:2]
328 args
= deepcopy(args
, memo
)
331 if listiter
is not None:
332 for item
in listiter
:
334 item
= deepcopy(item
, memo
)
336 if dictiter
is not None:
337 for key
, value
in dictiter
:
339 key
= deepcopy(key
, memo
)
340 value
= deepcopy(value
, memo
)
344 state
= deepcopy(state
, memo
)
345 if hasattr(y
, '__setstate__'):
346 y
.__setstate
__(state
)
348 if isinstance(state
, tuple) and len(state
) == 2:
349 state
, slotstate
= state
352 if state
is not None:
353 y
.__dict
__.update(state
)
354 if slotstate
is not None:
355 for key
, value
in slotstate
.iteritems():
356 setattr(y
, key
, value
)
363 # Helper for instance creation without calling __init__
368 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
369 {'abc': 'ABC'}, (), [], {}]
377 def __init__(self
, arg
=None):
380 if __name__
== '__main__':
387 def __getstate__(self
):
388 return {'a': self
.a
, 'arg': self
.arg
}
389 def __setstate__(self
, state
):
390 for key
, value
in state
.iteritems():
391 setattr(self
, key
, value
)
392 def __deepcopy__(self
, memo
=None):
393 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
396 c
= C('argument sketch')
406 l
.append({l
[1]: l
, 'xyz': l
[2]})
409 print map(repr.repr, l
)
410 print map(repr.repr, l1
)
411 print map(repr.repr, l2
)
412 print map(repr.repr, l3
)
415 print map(repr.repr, l
)
416 print map(repr.repr, l1
)
417 print map(repr.repr, l2
)
418 print map(repr.repr, l3
)
420 if __name__
== '__main__':