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 _keep_alive(x
, memo
):
264 """Keeps a reference to the object x in the memo.
266 Because we remember objects by their id, we have
267 to assure that possibly temporary objects are kept
268 alive by referencing them.
269 We store a reference at the id of the memo, which should
270 normally not be used unless someone tries to deepcopy
274 memo
[id(memo
)].append(x
)
276 # aha, this is the first one :-)
279 def _deepcopy_inst(x
, memo
):
280 if hasattr(x
, '__deepcopy__'):
281 return x
.__deepcopy
__(memo
)
282 if hasattr(x
, '__getinitargs__'):
283 args
= x
.__getinitargs
__()
284 args
= deepcopy(args
, memo
)
285 y
= x
.__class
__(*args
)
288 y
.__class
__ = x
.__class
__
290 if hasattr(x
, '__getstate__'):
291 state
= x
.__getstate
__()
294 state
= deepcopy(state
, memo
)
295 if hasattr(y
, '__setstate__'):
296 y
.__setstate
__(state
)
298 y
.__dict
__.update(state
)
300 d
[types
.InstanceType
] = _deepcopy_inst
302 def _reconstruct(x
, info
, deep
, memo
=None):
303 if isinstance(info
, str):
305 assert isinstance(info
, tuple)
309 assert n
in (2, 3, 4, 5)
310 callable, args
= info
[:2]
324 args
= deepcopy(args
, memo
)
327 if listiter
is not None:
328 for item
in listiter
:
330 item
= deepcopy(item
, memo
)
332 if dictiter
is not None:
333 for key
, value
in dictiter
:
335 key
= deepcopy(key
, memo
)
336 value
= deepcopy(value
, memo
)
340 state
= deepcopy(state
, memo
)
341 if hasattr(y
, '__setstate__'):
342 y
.__setstate
__(state
)
344 if isinstance(state
, tuple) and len(state
) == 2:
345 state
, slotstate
= state
348 if state
is not None:
349 y
.__dict
__.update(state
)
350 if slotstate
is not None:
351 for key
, value
in slotstate
.iteritems():
352 setattr(y
, key
, value
)
359 # Helper for instance creation without calling __init__
364 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
365 {'abc': 'ABC'}, (), [], {}]
373 def __init__(self
, arg
=None):
376 if __name__
== '__main__':
383 def __getstate__(self
):
384 return {'a': self
.a
, 'arg': self
.arg
}
385 def __setstate__(self
, state
):
386 for key
, value
in state
.iteritems():
387 setattr(self
, key
, value
)
388 def __deepcopy__(self
, memo
=None):
389 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
392 c
= C('argument sketch')
402 l
.append({l
[1]: l
, 'xyz': l
[2]})
405 print map(repr.repr, l
)
406 print map(repr.repr, l1
)
407 print map(repr.repr, l2
)
408 print map(repr.repr, l3
)
411 print map(repr.repr, l
)
412 print map(repr.repr, l1
)
413 print map(repr.repr, l2
)
414 print map(repr.repr, l3
)
416 if __name__
== '__main__':