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 in 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
= {}
102 d
[types
.NoneType
] = _copy_atomic
103 d
[types
.IntType
] = _copy_atomic
104 d
[types
.LongType
] = _copy_atomic
105 d
[types
.FloatType
] = _copy_atomic
106 d
[types
.BooleanType
] = _copy_atomic
108 d
[types
.ComplexType
] = _copy_atomic
109 except AttributeError:
111 d
[types
.StringType
] = _copy_atomic
113 d
[types
.UnicodeType
] = _copy_atomic
114 except AttributeError:
117 d
[types
.CodeType
] = _copy_atomic
118 except AttributeError:
120 d
[types
.TypeType
] = _copy_atomic
121 d
[types
.XRangeType
] = _copy_atomic
122 d
[types
.ClassType
] = _copy_atomic
123 d
[types
.BuiltinFunctionType
] = _copy_atomic
127 d
[types
.ListType
] = _copy_list
131 d
[types
.TupleType
] = _copy_tuple
135 d
[types
.DictionaryType
] = _copy_dict
136 if PyStringMap
is not None:
137 d
[PyStringMap
] = _copy_dict
140 if hasattr(x
, '__copy__'):
142 if hasattr(x
, '__getinitargs__'):
143 args
= x
.__getinitargs
__()
144 y
= x
.__class
__(*args
)
147 y
.__class
__ = x
.__class
__
148 if hasattr(x
, '__getstate__'):
149 state
= x
.__getstate
__()
152 if hasattr(y
, '__setstate__'):
153 y
.__setstate
__(state
)
155 y
.__dict
__.update(state
)
157 d
[types
.InstanceType
] = _copy_inst
161 def deepcopy(x
, memo
=None, _nil
=[]):
162 """Deep copy operation on arbitrary Python objects.
164 See the module's __doc__ string for more info.
171 y
= memo
.get(d
, _nil
)
177 copier
= _deepcopy_dispatch
.get(cls
)
182 issc
= issubclass(cls
, type)
183 except TypeError: # cls is not a class (old Boost; see SF #502085)
186 y
= _deepcopy_atomic(x
, memo
)
188 copier
= getattr(x
, "__deepcopy__", None)
192 reductor
= dispatch_table
.get(cls
)
196 reductor
= getattr(x
, "__reduce_ex__", None)
200 reductor
= getattr(x
, "__reduce__", None)
205 "un(deep)copyable object of type %s" % cls
)
206 y
= _reconstruct(x
, rv
, 1, memo
)
209 _keep_alive(x
, memo
) # Make sure x lives at least as long as d
212 _deepcopy_dispatch
= d
= {}
214 def _deepcopy_atomic(x
, memo
):
216 d
[types
.NoneType
] = _deepcopy_atomic
217 d
[types
.IntType
] = _deepcopy_atomic
218 d
[types
.LongType
] = _deepcopy_atomic
219 d
[types
.FloatType
] = _deepcopy_atomic
220 d
[types
.BooleanType
] = _deepcopy_atomic
222 d
[types
.ComplexType
] = _deepcopy_atomic
223 except AttributeError:
225 d
[types
.StringType
] = _deepcopy_atomic
227 d
[types
.UnicodeType
] = _deepcopy_atomic
228 except AttributeError:
231 d
[types
.CodeType
] = _deepcopy_atomic
232 except AttributeError:
234 d
[types
.TypeType
] = _deepcopy_atomic
235 d
[types
.XRangeType
] = _deepcopy_atomic
236 d
[types
.ClassType
] = _deepcopy_atomic
237 d
[types
.BuiltinFunctionType
] = _deepcopy_atomic
239 def _deepcopy_list(x
, memo
):
243 y
.append(deepcopy(a
, memo
))
245 d
[types
.ListType
] = _deepcopy_list
247 def _deepcopy_tuple(x
, memo
):
250 y
.append(deepcopy(a
, memo
))
256 for i
in range(len(x
)):
264 d
[types
.TupleType
] = _deepcopy_tuple
266 def _deepcopy_dict(x
, memo
):
269 for key
, value
in x
.iteritems():
270 y
[deepcopy(key
, memo
)] = deepcopy(value
, memo
)
272 d
[types
.DictionaryType
] = _deepcopy_dict
273 if PyStringMap
is not None:
274 d
[PyStringMap
] = _deepcopy_dict
276 def _keep_alive(x
, memo
):
277 """Keeps a reference to the object x in the memo.
279 Because we remember objects by their id, we have
280 to assure that possibly temporary objects are kept
281 alive by referencing them.
282 We store a reference at the id of the memo, which should
283 normally not be used unless someone tries to deepcopy
287 memo
[id(memo
)].append(x
)
289 # aha, this is the first one :-)
292 def _deepcopy_inst(x
, memo
):
293 if hasattr(x
, '__deepcopy__'):
294 return x
.__deepcopy
__(memo
)
295 if hasattr(x
, '__getinitargs__'):
296 args
= x
.__getinitargs
__()
297 args
= deepcopy(args
, memo
)
298 y
= x
.__class
__(*args
)
301 y
.__class
__ = x
.__class
__
303 if hasattr(x
, '__getstate__'):
304 state
= x
.__getstate
__()
307 state
= deepcopy(state
, memo
)
308 if hasattr(y
, '__setstate__'):
309 y
.__setstate
__(state
)
311 y
.__dict
__.update(state
)
313 d
[types
.InstanceType
] = _deepcopy_inst
315 def _reconstruct(x
, info
, deep
, memo
=None):
316 if isinstance(info
, str):
318 assert isinstance(info
, tuple)
322 assert n
in (2, 3, 4, 5)
323 callable, args
= info
[:2]
337 args
= deepcopy(args
, memo
)
340 if listiter
is not None:
341 for item
in listiter
:
343 item
= deepcopy(item
, memo
)
345 if dictiter
is not None:
346 for key
, value
in dictiter
:
348 key
= deepcopy(key
, memo
)
349 value
= deepcopy(value
, memo
)
353 state
= deepcopy(state
, memo
)
354 if hasattr(y
, '__setstate__'):
355 y
.__setstate
__(state
)
357 if isinstance(state
, tuple) and len(state
) == 2:
358 state
, slotstate
= state
361 if state
is not None:
362 y
.__dict
__.update(state
)
363 if slotstate
is not None:
364 for key
, value
in slotstate
.iteritems():
365 setattr(y
, key
, value
)
372 # Helper for instance creation without calling __init__
377 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
378 {'abc': 'ABC'}, (), [], {}]
386 def __init__(self
, arg
=None):
389 if __name__
== '__main__':
396 def __getstate__(self
):
397 return {'a': self
.a
, 'arg': self
.arg
}
398 def __setstate__(self
, state
):
399 for key
, value
in state
.iteritems():
400 setattr(self
, key
, value
)
401 def __deepcopy__(self
, memo
=None):
402 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
405 c
= C('argument sketch')
415 l
.append({l
[1]: l
, 'xyz': l
[2]})
418 print map(repr.repr, l
)
419 print map(repr.repr, l1
)
420 print map(repr.repr, l2
)
421 print map(repr.repr, l3
)
424 print map(repr.repr, l
)
425 print map(repr.repr, l1
)
426 print map(repr.repr, l2
)
427 print map(repr.repr, l3
)
429 if __name__
== '__main__':