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
, type(Ellipsis),
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
[type(Ellipsis)] = _deepcopy_atomic
201 d
[int] = _deepcopy_atomic
202 d
[long] = _deepcopy_atomic
203 d
[float] = _deepcopy_atomic
204 d
[bool] = _deepcopy_atomic
206 d
[complex] = _deepcopy_atomic
209 d
[str] = _deepcopy_atomic
211 d
[unicode] = _deepcopy_atomic
215 d
[types
.CodeType
] = _deepcopy_atomic
216 except AttributeError:
218 d
[type] = _deepcopy_atomic
219 d
[xrange] = _deepcopy_atomic
220 d
[types
.ClassType
] = _deepcopy_atomic
221 d
[types
.BuiltinFunctionType
] = _deepcopy_atomic
222 d
[types
.FunctionType
] = _deepcopy_atomic
224 def _deepcopy_list(x
, memo
):
228 y
.append(deepcopy(a
, memo
))
230 d
[list] = _deepcopy_list
232 def _deepcopy_tuple(x
, memo
):
235 y
.append(deepcopy(a
, memo
))
241 for i
in range(len(x
)):
249 d
[tuple] = _deepcopy_tuple
251 def _deepcopy_dict(x
, memo
):
254 for key
, value
in x
.iteritems():
255 y
[deepcopy(key
, memo
)] = deepcopy(value
, memo
)
257 d
[dict] = _deepcopy_dict
258 if PyStringMap
is not None:
259 d
[PyStringMap
] = _deepcopy_dict
261 def _keep_alive(x
, memo
):
262 """Keeps a reference to the object x in the memo.
264 Because we remember objects by their id, we have
265 to assure that possibly temporary objects are kept
266 alive by referencing them.
267 We store a reference at the id of the memo, which should
268 normally not be used unless someone tries to deepcopy
272 memo
[id(memo
)].append(x
)
274 # aha, this is the first one :-)
277 def _deepcopy_inst(x
, memo
):
278 if hasattr(x
, '__deepcopy__'):
279 return x
.__deepcopy
__(memo
)
280 if hasattr(x
, '__getinitargs__'):
281 args
= x
.__getinitargs
__()
282 args
= deepcopy(args
, memo
)
283 y
= x
.__class
__(*args
)
286 y
.__class
__ = x
.__class
__
288 if hasattr(x
, '__getstate__'):
289 state
= x
.__getstate
__()
292 state
= deepcopy(state
, memo
)
293 if hasattr(y
, '__setstate__'):
294 y
.__setstate
__(state
)
296 y
.__dict
__.update(state
)
298 d
[types
.InstanceType
] = _deepcopy_inst
300 def _reconstruct(x
, info
, deep
, memo
=None):
301 if isinstance(info
, str):
303 assert isinstance(info
, tuple)
307 assert n
in (2, 3, 4, 5)
308 callable, args
= info
[:2]
322 args
= deepcopy(args
, memo
)
325 if listiter
is not None:
326 for item
in listiter
:
328 item
= deepcopy(item
, memo
)
330 if dictiter
is not None:
331 for key
, value
in dictiter
:
333 key
= deepcopy(key
, memo
)
334 value
= deepcopy(value
, memo
)
338 state
= deepcopy(state
, memo
)
339 if hasattr(y
, '__setstate__'):
340 y
.__setstate
__(state
)
342 if isinstance(state
, tuple) and len(state
) == 2:
343 state
, slotstate
= state
346 if state
is not None:
347 y
.__dict
__.update(state
)
348 if slotstate
is not None:
349 for key
, value
in slotstate
.iteritems():
350 setattr(y
, key
, value
)
357 # Helper for instance creation without calling __init__
362 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
363 {'abc': 'ABC'}, (), [], {}]
371 def __init__(self
, arg
=None):
374 if __name__
== '__main__':
381 def __getstate__(self
):
382 return {'a': self
.a
, 'arg': self
.arg
}
383 def __setstate__(self
, state
):
384 for key
, value
in state
.iteritems():
385 setattr(self
, key
, value
)
386 def __deepcopy__(self
, memo
=None):
387 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
390 c
= C('argument sketch')
400 l
.append({l
[1]: l
, 'xyz': l
[2]})
403 print map(repr.repr, l
)
404 print map(repr.repr, l1
)
405 print map(repr.repr, l2
)
406 print map(repr.repr, l3
)
409 print map(repr.repr, l
)
410 print map(repr.repr, l1
)
411 print map(repr.repr, l2
)
412 print map(repr.repr, l3
)
414 if __name__
== '__main__':