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.
52 from copy_reg
import dispatch_table
54 class Error(Exception):
56 error
= Error
# backward compatibility
59 from org
.python
.core
import PyStringMap
63 __all__
= ["Error", "copy", "deepcopy"]
66 """Shallow copy operation on arbitrary Python objects.
68 See the module's __doc__ string for more info.
73 copier
= _copy_dispatch
.get(cls
)
77 copier
= getattr(cls
, "__copy__", None)
81 reductor
= dispatch_table
.get(cls
)
85 reductor
= getattr(x
, "__reduce_ex__", None)
89 reductor
= getattr(x
, "__reduce__", None)
93 raise Error("un(shallow)copyable object of type %s" % cls
)
95 return _reconstruct(x
, rv
, 0)
98 _copy_dispatch
= d
= {}
100 def _copy_immutable(x
):
102 for t
in (type(None), int, long, float, bool, str, tuple,
103 frozenset, type, xrange, types
.ClassType
,
104 types
.BuiltinFunctionType
,
106 d
[t
] = _copy_immutable
107 for name
in ("ComplexType", "UnicodeType", "CodeType"):
108 t
= getattr(types
, name
, None)
110 d
[t
] = _copy_immutable
112 def _copy_with_constructor(x
):
114 for t
in (list, dict, set):
115 d
[t
] = _copy_with_constructor
117 def _copy_with_copy_method(x
):
119 if PyStringMap
is not None:
120 d
[PyStringMap
] = _copy_with_copy_method
123 if hasattr(x
, '__copy__'):
125 if hasattr(x
, '__getinitargs__'):
126 args
= x
.__getinitargs
__()
127 y
= x
.__class
__(*args
)
130 y
.__class
__ = x
.__class
__
131 if hasattr(x
, '__getstate__'):
132 state
= x
.__getstate
__()
135 if hasattr(y
, '__setstate__'):
136 y
.__setstate
__(state
)
138 y
.__dict
__.update(state
)
140 d
[types
.InstanceType
] = _copy_inst
144 def deepcopy(x
, memo
=None, _nil
=[]):
145 """Deep copy operation on arbitrary Python objects.
147 See the module's __doc__ string for more info.
154 y
= memo
.get(d
, _nil
)
160 copier
= _deepcopy_dispatch
.get(cls
)
165 issc
= issubclass(cls
, type)
166 except TypeError: # cls is not a class (old Boost; see SF #502085)
169 y
= _deepcopy_atomic(x
, memo
)
171 copier
= getattr(x
, "__deepcopy__", None)
175 reductor
= dispatch_table
.get(cls
)
179 reductor
= getattr(x
, "__reduce_ex__", None)
183 reductor
= getattr(x
, "__reduce__", None)
188 "un(deep)copyable object of type %s" % cls
)
189 y
= _reconstruct(x
, rv
, 1, memo
)
192 _keep_alive(x
, memo
) # Make sure x lives at least as long as d
195 _deepcopy_dispatch
= d
= {}
197 def _deepcopy_atomic(x
, memo
):
199 d
[type(None)] = _deepcopy_atomic
200 d
[int] = _deepcopy_atomic
201 d
[long] = _deepcopy_atomic
202 d
[float] = _deepcopy_atomic
203 d
[bool] = _deepcopy_atomic
205 d
[complex] = _deepcopy_atomic
208 d
[str] = _deepcopy_atomic
210 d
[unicode] = _deepcopy_atomic
214 d
[types
.CodeType
] = _deepcopy_atomic
215 except AttributeError:
217 d
[type] = _deepcopy_atomic
218 d
[xrange] = _deepcopy_atomic
219 d
[types
.ClassType
] = _deepcopy_atomic
220 d
[types
.BuiltinFunctionType
] = _deepcopy_atomic
221 d
[types
.FunctionType
] = _deepcopy_atomic
223 def _deepcopy_list(x
, memo
):
227 y
.append(deepcopy(a
, memo
))
229 d
[list] = _deepcopy_list
231 def _deepcopy_tuple(x
, memo
):
234 y
.append(deepcopy(a
, memo
))
240 for i
in range(len(x
)):
248 d
[tuple] = _deepcopy_tuple
250 def _deepcopy_dict(x
, memo
):
253 for key
, value
in x
.iteritems():
254 y
[deepcopy(key
, memo
)] = deepcopy(value
, memo
)
256 d
[dict] = _deepcopy_dict
257 if PyStringMap
is not None:
258 d
[PyStringMap
] = _deepcopy_dict
260 def _keep_alive(x
, memo
):
261 """Keeps a reference to the object x in the memo.
263 Because we remember objects by their id, we have
264 to assure that possibly temporary objects are kept
265 alive by referencing them.
266 We store a reference at the id of the memo, which should
267 normally not be used unless someone tries to deepcopy
271 memo
[id(memo
)].append(x
)
273 # aha, this is the first one :-)
276 def _deepcopy_inst(x
, memo
):
277 if hasattr(x
, '__deepcopy__'):
278 return x
.__deepcopy
__(memo
)
279 if hasattr(x
, '__getinitargs__'):
280 args
= x
.__getinitargs
__()
281 args
= deepcopy(args
, memo
)
282 y
= x
.__class
__(*args
)
285 y
.__class
__ = x
.__class
__
287 if hasattr(x
, '__getstate__'):
288 state
= x
.__getstate
__()
291 state
= deepcopy(state
, memo
)
292 if hasattr(y
, '__setstate__'):
293 y
.__setstate
__(state
)
295 y
.__dict
__.update(state
)
297 d
[types
.InstanceType
] = _deepcopy_inst
299 def _reconstruct(x
, info
, deep
, memo
=None):
300 if isinstance(info
, str):
302 assert isinstance(info
, tuple)
306 assert n
in (2, 3, 4, 5)
307 callable, args
= info
[:2]
321 args
= deepcopy(args
, memo
)
324 if listiter
is not None:
325 for item
in listiter
:
327 item
= deepcopy(item
, memo
)
329 if dictiter
is not None:
330 for key
, value
in dictiter
:
332 key
= deepcopy(key
, memo
)
333 value
= deepcopy(value
, memo
)
337 state
= deepcopy(state
, memo
)
338 if hasattr(y
, '__setstate__'):
339 y
.__setstate
__(state
)
341 if isinstance(state
, tuple) and len(state
) == 2:
342 state
, slotstate
= state
345 if state
is not None:
346 y
.__dict
__.update(state
)
347 if slotstate
is not None:
348 for key
, value
in slotstate
.iteritems():
349 setattr(y
, key
, value
)
356 # Helper for instance creation without calling __init__
361 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
362 {'abc': 'ABC'}, (), [], {}]
370 def __init__(self
, arg
=None):
373 if __name__
== '__main__':
380 def __getstate__(self
):
381 return {'a': self
.a
, 'arg': self
.arg
}
382 def __setstate__(self
, state
):
383 for key
, value
in state
.iteritems():
384 setattr(self
, key
, value
)
385 def __deepcopy__(self
, memo
=None):
386 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
389 c
= C('argument sketch')
399 l
.append({l
[1]: l
, 'xyz': l
[2]})
402 print map(repr.repr, l
)
403 print map(repr.repr, l1
)
404 print map(repr.repr, l2
)
405 print map(repr.repr, l3
)
408 print map(repr.repr, l
)
409 print map(repr.repr, l1
)
410 print map(repr.repr, l2
)
411 print map(repr.repr, l3
)
413 if __name__
== '__main__':