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
126 d
[types
.ListType
] = _copy_list
130 d
[types
.TupleType
] = _copy_tuple
134 d
[types
.DictionaryType
] = _copy_dict
135 if PyStringMap
is not None:
136 d
[PyStringMap
] = _copy_dict
139 if hasattr(x
, '__copy__'):
141 if hasattr(x
, '__getinitargs__'):
142 args
= x
.__getinitargs
__()
143 y
= x
.__class
__(*args
)
146 y
.__class
__ = x
.__class
__
147 if hasattr(x
, '__getstate__'):
148 state
= x
.__getstate
__()
151 if hasattr(y
, '__setstate__'):
152 y
.__setstate
__(state
)
154 y
.__dict
__.update(state
)
156 d
[types
.InstanceType
] = _copy_inst
160 def deepcopy(x
, memo
=None, _nil
=[]):
161 """Deep copy operation on arbitrary Python objects.
163 See the module's __doc__ string for more info.
170 y
= memo
.get(d
, _nil
)
176 copier
= _deepcopy_dispatch
.get(cls
)
181 issc
= issubclass(cls
, type)
182 except TypeError: # cls is not a class (old Boost; see SF #502085)
185 y
= _deepcopy_atomic(x
, memo
)
187 copier
= getattr(x
, "__deepcopy__", None)
191 reductor
= dispatch_table
.get(cls
)
195 reductor
= getattr(x
, "__reduce_ex__", None)
199 reductor
= getattr(x
, "__reduce__", None)
204 "un(deep)copyable object of type %s" % cls
)
205 y
= _reconstruct(x
, rv
, 1, memo
)
208 _keep_alive(x
, memo
) # Make sure x lives at least as long as d
211 _deepcopy_dispatch
= d
= {}
213 def _deepcopy_atomic(x
, memo
):
215 d
[types
.NoneType
] = _deepcopy_atomic
216 d
[types
.IntType
] = _deepcopy_atomic
217 d
[types
.LongType
] = _deepcopy_atomic
218 d
[types
.FloatType
] = _deepcopy_atomic
219 d
[types
.BooleanType
] = _deepcopy_atomic
221 d
[types
.ComplexType
] = _deepcopy_atomic
222 except AttributeError:
224 d
[types
.StringType
] = _deepcopy_atomic
226 d
[types
.UnicodeType
] = _deepcopy_atomic
227 except AttributeError:
230 d
[types
.CodeType
] = _deepcopy_atomic
231 except AttributeError:
233 d
[types
.TypeType
] = _deepcopy_atomic
234 d
[types
.XRangeType
] = _deepcopy_atomic
235 d
[types
.ClassType
] = _deepcopy_atomic
237 def _deepcopy_list(x
, memo
):
241 y
.append(deepcopy(a
, memo
))
243 d
[types
.ListType
] = _deepcopy_list
245 def _deepcopy_tuple(x
, memo
):
248 y
.append(deepcopy(a
, memo
))
254 for i
in range(len(x
)):
262 d
[types
.TupleType
] = _deepcopy_tuple
264 def _deepcopy_dict(x
, memo
):
267 for key
, value
in x
.iteritems():
268 y
[deepcopy(key
, memo
)] = deepcopy(value
, memo
)
270 d
[types
.DictionaryType
] = _deepcopy_dict
271 if PyStringMap
is not None:
272 d
[PyStringMap
] = _deepcopy_dict
274 def _keep_alive(x
, memo
):
275 """Keeps a reference to the object x in the memo.
277 Because we remember objects by their id, we have
278 to assure that possibly temporary objects are kept
279 alive by referencing them.
280 We store a reference at the id of the memo, which should
281 normally not be used unless someone tries to deepcopy
285 memo
[id(memo
)].append(x
)
287 # aha, this is the first one :-)
290 def _deepcopy_inst(x
, memo
):
291 if hasattr(x
, '__deepcopy__'):
292 return x
.__deepcopy
__(memo
)
293 if hasattr(x
, '__getinitargs__'):
294 args
= x
.__getinitargs
__()
295 args
= deepcopy(args
, memo
)
296 y
= x
.__class
__(*args
)
299 y
.__class
__ = x
.__class
__
301 if hasattr(x
, '__getstate__'):
302 state
= x
.__getstate
__()
305 state
= deepcopy(state
, memo
)
306 if hasattr(y
, '__setstate__'):
307 y
.__setstate
__(state
)
309 y
.__dict
__.update(state
)
311 d
[types
.InstanceType
] = _deepcopy_inst
313 def _reconstruct(x
, info
, deep
, memo
=None):
314 if isinstance(info
, str):
316 assert isinstance(info
, tuple)
320 assert n
in (2, 3, 4, 5)
321 callable, args
= info
[:2]
335 args
= deepcopy(args
, memo
)
337 if listiter
is not None:
338 for item
in listiter
:
340 item
= deepcopy(item
, memo
)
342 if dictiter
is not None:
343 for key
, value
in dictiter
:
345 key
= deepcopy(key
, memo
)
346 value
= deepcopy(value
, memo
)
350 state
= deepcopy(state
, memo
)
351 if hasattr(y
, '__setstate__'):
352 y
.__setstate
__(state
)
354 if isinstance(state
, tuple) and len(state
) == 2:
355 state
, slotstate
= state
358 if state
is not None:
359 y
.__dict
__.update(state
)
360 if slotstate
is not None:
361 for key
, value
in slotstate
.iteritems():
362 setattr(y
, key
, value
)
369 # Helper for instance creation without calling __init__
374 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
375 {'abc': 'ABC'}, (), [], {}]
383 def __init__(self
, arg
=None):
386 if __name__
== '__main__':
393 def __getstate__(self
):
394 return {'a': self
.a
, 'arg': self
.arg
}
395 def __setstate__(self
, state
):
396 for key
, value
in state
.iteritems():
397 setattr(self
, key
, value
)
398 def __deepcopy__(self
, memo
=None):
399 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
402 c
= C('argument sketch')
412 l
.append({l
[1]: l
, 'xyz': l
[2]})
415 print map(repr.repr, l
)
416 print map(repr.repr, l1
)
417 print map(repr.repr, l2
)
418 print map(repr.repr, l3
)
421 print map(repr.repr, l
)
422 print map(repr.repr, l1
)
423 print map(repr.repr, l2
)
424 print map(repr.repr, l3
)
426 if __name__
== '__main__':