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
):
105 d
[t
] = _copy_immutable
106 for name
in ("ComplexType", "UnicodeType", "CodeType"):
107 t
= getattr(types
, name
, None)
109 d
[t
] = _copy_immutable
111 def _copy_with_constructor(x
):
113 for t
in (list, dict, set):
114 d
[t
] = _copy_with_constructor
116 def _copy_with_copy_method(x
):
118 if PyStringMap
is not None:
119 d
[PyStringMap
] = _copy_with_copy_method
122 if hasattr(x
, '__copy__'):
124 if hasattr(x
, '__getinitargs__'):
125 args
= x
.__getinitargs
__()
126 y
= x
.__class
__(*args
)
129 y
.__class
__ = x
.__class
__
130 if hasattr(x
, '__getstate__'):
131 state
= x
.__getstate
__()
134 if hasattr(y
, '__setstate__'):
135 y
.__setstate
__(state
)
137 y
.__dict
__.update(state
)
139 d
[types
.InstanceType
] = _copy_inst
143 def deepcopy(x
, memo
=None, _nil
=[]):
144 """Deep copy operation on arbitrary Python objects.
146 See the module's __doc__ string for more info.
153 y
= memo
.get(d
, _nil
)
159 copier
= _deepcopy_dispatch
.get(cls
)
164 issc
= issubclass(cls
, type)
165 except TypeError: # cls is not a class (old Boost; see SF #502085)
168 y
= _deepcopy_atomic(x
, memo
)
170 copier
= getattr(x
, "__deepcopy__", None)
174 reductor
= dispatch_table
.get(cls
)
178 reductor
= getattr(x
, "__reduce_ex__", None)
182 reductor
= getattr(x
, "__reduce__", None)
187 "un(deep)copyable object of type %s" % cls
)
188 y
= _reconstruct(x
, rv
, 1, memo
)
191 _keep_alive(x
, memo
) # Make sure x lives at least as long as d
194 _deepcopy_dispatch
= d
= {}
196 def _deepcopy_atomic(x
, memo
):
198 d
[type(None)] = _deepcopy_atomic
199 d
[int] = _deepcopy_atomic
200 d
[long] = _deepcopy_atomic
201 d
[float] = _deepcopy_atomic
202 d
[bool] = _deepcopy_atomic
204 d
[complex] = _deepcopy_atomic
207 d
[str] = _deepcopy_atomic
209 d
[unicode] = _deepcopy_atomic
213 d
[types
.CodeType
] = _deepcopy_atomic
214 except AttributeError:
216 d
[type] = _deepcopy_atomic
217 d
[xrange] = _deepcopy_atomic
218 d
[types
.ClassType
] = _deepcopy_atomic
219 d
[types
.BuiltinFunctionType
] = _deepcopy_atomic
221 def _deepcopy_list(x
, memo
):
225 y
.append(deepcopy(a
, memo
))
227 d
[list] = _deepcopy_list
229 def _deepcopy_tuple(x
, memo
):
232 y
.append(deepcopy(a
, memo
))
238 for i
in range(len(x
)):
246 d
[tuple] = _deepcopy_tuple
248 def _deepcopy_dict(x
, memo
):
251 for key
, value
in x
.iteritems():
252 y
[deepcopy(key
, memo
)] = deepcopy(value
, memo
)
254 d
[dict] = _deepcopy_dict
255 if PyStringMap
is not None:
256 d
[PyStringMap
] = _deepcopy_dict
258 def _keep_alive(x
, memo
):
259 """Keeps a reference to the object x in the memo.
261 Because we remember objects by their id, we have
262 to assure that possibly temporary objects are kept
263 alive by referencing them.
264 We store a reference at the id of the memo, which should
265 normally not be used unless someone tries to deepcopy
269 memo
[id(memo
)].append(x
)
271 # aha, this is the first one :-)
274 def _deepcopy_inst(x
, memo
):
275 if hasattr(x
, '__deepcopy__'):
276 return x
.__deepcopy
__(memo
)
277 if hasattr(x
, '__getinitargs__'):
278 args
= x
.__getinitargs
__()
279 args
= deepcopy(args
, memo
)
280 y
= x
.__class
__(*args
)
283 y
.__class
__ = x
.__class
__
285 if hasattr(x
, '__getstate__'):
286 state
= x
.__getstate
__()
289 state
= deepcopy(state
, memo
)
290 if hasattr(y
, '__setstate__'):
291 y
.__setstate
__(state
)
293 y
.__dict
__.update(state
)
295 d
[types
.InstanceType
] = _deepcopy_inst
297 def _reconstruct(x
, info
, deep
, memo
=None):
298 if isinstance(info
, str):
300 assert isinstance(info
, tuple)
304 assert n
in (2, 3, 4, 5)
305 callable, args
= info
[:2]
319 args
= deepcopy(args
, memo
)
322 if listiter
is not None:
323 for item
in listiter
:
325 item
= deepcopy(item
, memo
)
327 if dictiter
is not None:
328 for key
, value
in dictiter
:
330 key
= deepcopy(key
, memo
)
331 value
= deepcopy(value
, memo
)
335 state
= deepcopy(state
, memo
)
336 if hasattr(y
, '__setstate__'):
337 y
.__setstate
__(state
)
339 if isinstance(state
, tuple) and len(state
) == 2:
340 state
, slotstate
= state
343 if state
is not None:
344 y
.__dict
__.update(state
)
345 if slotstate
is not None:
346 for key
, value
in slotstate
.iteritems():
347 setattr(y
, key
, value
)
354 # Helper for instance creation without calling __init__
359 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
360 {'abc': 'ABC'}, (), [], {}]
368 def __init__(self
, arg
=None):
371 if __name__
== '__main__':
378 def __getstate__(self
):
379 return {'a': self
.a
, 'arg': self
.arg
}
380 def __setstate__(self
, state
):
381 for key
, value
in state
.iteritems():
382 setattr(self
, key
, value
)
383 def __deepcopy__(self
, memo
=None):
384 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
387 c
= C('argument sketch')
397 l
.append({l
[1]: l
, 'xyz': l
[2]})
400 print map(repr.repr, l
)
401 print map(repr.repr, l1
)
402 print map(repr.repr, l2
)
403 print map(repr.repr, l3
)
406 print map(repr.repr, l
)
407 print map(repr.repr, l1
)
408 print map(repr.repr, l2
)
409 print map(repr.repr, l3
)
411 if __name__
== '__main__':