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.
60 from org.python.core
import PyStringMap
64 __all__ = [
"Error",
"error",
"copy",
"deepcopy"]
67 """Shallow copy operation on arbitrary Python objects.
69 See the module's __doc__ string for more info.
73 copierfunction = _copy_dispatch[type(x)]
77 except AttributeError:
79 reductor = x.__reduce__
80 except AttributeError:
82 "un(shallow)copyable object of type %s" % type(x)
84 y = _reconstruct(x, reductor(), 0)
91 _copy_dispatch = d = {}
95 d[types.NoneType] = _copy_atomic
96 d[types.IntType] = _copy_atomic
97 d[types.LongType] = _copy_atomic
98 d[types.FloatType] = _copy_atomic
100 d[types.ComplexType] = _copy_atomic
101 except AttributeError:
103 d[types.StringType] = _copy_atomic
105 d[types.UnicodeType] = _copy_atomic
106 except AttributeError:
109 d[types.CodeType] = _copy_atomic
110 except AttributeError:
112 d[types.TypeType] = _copy_atomic
113 d[types.XRangeType] = _copy_atomic
114 d[types.ClassType] = _copy_atomic
118 d[types.ListType] = _copy_list
122 d[types.TupleType] = _copy_tuple
126 d[types.DictionaryType] = _copy_dict
127 if PyStringMap
is not None:
128 d[PyStringMap] = _copy_dict
131 if hasattr(x,
'__copy__'):
133 if hasattr(x,
'__getinitargs__'):
134 args = x.__getinitargs__()
135 y = apply(x.__class__, args)
138 y.__class__ = x.__class__
139 if hasattr(x,
'__getstate__'):
140 state = x.__getstate__()
143 if hasattr(y,
'__setstate__'):
144 y.__setstate__(state)
146 y.__dict__.update(state)
148 d[types.InstanceType] = _copy_inst
153 """Deep copy operation on arbitrary Python objects.
155 See the module's __doc__ string for more info.
164 copierfunction = _deepcopy_dispatch[type(x)]
167 copier = x.__deepcopy__
168 except AttributeError:
170 reductor = x.__reduce__
171 except AttributeError:
173 "un-deep-copyable object of type %s" % type(x)
175 y = _reconstruct(x, reductor(), 1, memo)
179 y = copierfunction(x, memo)
183 _deepcopy_dispatch = d = {}
185 def _deepcopy_atomic(x, memo):
187 d[types.NoneType] = _deepcopy_atomic
188 d[types.IntType] = _deepcopy_atomic
189 d[types.LongType] = _deepcopy_atomic
190 d[types.FloatType] = _deepcopy_atomic
192 d[types.ComplexType] = _deepcopy_atomic
193 except AttributeError:
195 d[types.StringType] = _deepcopy_atomic
197 d[types.UnicodeType] = _deepcopy_atomic
198 except AttributeError:
201 d[types.CodeType] = _deepcopy_atomic
202 except AttributeError:
204 d[types.TypeType] = _deepcopy_atomic
205 d[types.XRangeType] = _deepcopy_atomic
207 def _deepcopy_list(x, memo):
213 d[types.ListType] = _deepcopy_list
215 def _deepcopy_tuple(x, memo):
224 for i
in range(len(x)):
232 d[types.TupleType] = _deepcopy_tuple
234 def _deepcopy_dict(x, memo):
240 d[types.DictionaryType] = _deepcopy_dict
241 if PyStringMap
is not None:
242 d[PyStringMap] = _deepcopy_dict
244 def _keep_alive(x, memo):
245 """Keeps a reference to the object x in the memo.
247 Because we remember objects by their id, we have
248 to assure that possibly temporary objects are kept
249 alive by referencing them.
250 We store a reference at the id of the memo, which should
251 normally not be used unless someone tries to deepcopy
260 def _deepcopy_inst(x, memo):
261 if hasattr(x,
'__deepcopy__'):
262 return x.__deepcopy__(memo)
263 if hasattr(x,
'__getinitargs__'):
264 args = x.__getinitargs__()
265 _keep_alive(args, memo)
267 y = apply(x.__class__, args)
270 y.__class__ = x.__class__
272 if hasattr(x,
'__getstate__'):
273 state = x.__getstate__()
274 _keep_alive(state, memo)
278 if hasattr(y,
'__setstate__'):
279 y.__setstate__(state)
281 y.__dict__.update(state)
283 d[types.InstanceType] = _deepcopy_inst
285 def _reconstruct(x, info, deep, memo=None):
286 if isinstance(info, str):
288 assert isinstance(info, tuple)
293 callable, args = info[:2]
304 y.__dict__.update(state)
316 l = [
None, 1, 2L, 3.14,
'xyzzy', (1, 2L), [3.14,
'abc'],
317 {
'abc':
'ABC'}, (), [], {}]
328 if __name__ ==
'__main__':
336 return {
'a': self.a,
'arg': self.arg}
338 for key
in state.keys():
339 setattr(self, key, state[key])
340 def __deepcopy__(self, memo = None):
341 new = self.__class__(
deepcopy(self.arg, memo))
344 c = C(
'argument sketch')
354 l.append({l[1]: l,
'xyz': l[2]})
357 print map(repr.repr, l)
358 print map(repr.repr, l1)
359 print map(repr.repr, l2)
360 print map(repr.repr, l3)
363 print map(repr.repr, l)
364 print map(repr.repr, l1)
365 print map(repr.repr, l2)
366 print map(repr.repr, l3)
368 if __name__ ==
'__main__':