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.
51 # XXX need to support copy_reg here too...
55 class Error(Exception):
57 error
= Error
# backward compatibility
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
152 def deepcopy(x
, memo
= None):
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 issc
= issubclass(type(x
), type)
171 y
= _deepcopy_dispatch
[type](x
, memo
)
174 copier
= x
.__deepcopy
__
175 except AttributeError:
177 reductor
= x
.__reduce
__
178 except AttributeError:
180 "un-deep-copyable object of type %s" % type(x
)
182 y
= _reconstruct(x
, reductor(), 1, memo
)
186 y
= copierfunction(x
, memo
)
188 _keep_alive(x
, memo
) # Make sure x lives at least as long as d
191 _deepcopy_dispatch
= d
= {}
193 def _deepcopy_atomic(x
, memo
):
195 d
[types
.NoneType
] = _deepcopy_atomic
196 d
[types
.IntType
] = _deepcopy_atomic
197 d
[types
.LongType
] = _deepcopy_atomic
198 d
[types
.FloatType
] = _deepcopy_atomic
200 d
[types
.ComplexType
] = _deepcopy_atomic
201 except AttributeError:
203 d
[types
.StringType
] = _deepcopy_atomic
205 d
[types
.UnicodeType
] = _deepcopy_atomic
206 except AttributeError:
209 d
[types
.CodeType
] = _deepcopy_atomic
210 except AttributeError:
212 d
[types
.TypeType
] = _deepcopy_atomic
213 d
[types
.XRangeType
] = _deepcopy_atomic
215 def _deepcopy_list(x
, memo
):
219 y
.append(deepcopy(a
, memo
))
221 d
[types
.ListType
] = _deepcopy_list
223 def _deepcopy_tuple(x
, memo
):
226 y
.append(deepcopy(a
, memo
))
232 for i
in range(len(x
)):
240 d
[types
.TupleType
] = _deepcopy_tuple
242 def _deepcopy_dict(x
, memo
):
245 for key
, value
in x
.iteritems():
246 y
[deepcopy(key
, memo
)] = deepcopy(value
, memo
)
248 d
[types
.DictionaryType
] = _deepcopy_dict
249 if PyStringMap
is not None:
250 d
[PyStringMap
] = _deepcopy_dict
252 def _keep_alive(x
, memo
):
253 """Keeps a reference to the object x in the memo.
255 Because we remember objects by their id, we have
256 to assure that possibly temporary objects are kept
257 alive by referencing them.
258 We store a reference at the id of the memo, which should
259 normally not be used unless someone tries to deepcopy
263 memo
[id(memo
)].append(x
)
265 # aha, this is the first one :-)
268 def _deepcopy_inst(x
, memo
):
269 if hasattr(x
, '__deepcopy__'):
270 return x
.__deepcopy
__(memo
)
271 if hasattr(x
, '__getinitargs__'):
272 args
= x
.__getinitargs
__()
273 args
= deepcopy(args
, memo
)
274 y
= apply(x
.__class
__, args
)
277 y
.__class
__ = x
.__class
__
279 if hasattr(x
, '__getstate__'):
280 state
= x
.__getstate
__()
283 state
= deepcopy(state
, memo
)
284 if hasattr(y
, '__setstate__'):
285 y
.__setstate
__(state
)
287 y
.__dict
__.update(state
)
289 d
[types
.InstanceType
] = _deepcopy_inst
291 def _reconstruct(x
, info
, deep
, memo
=None):
292 if isinstance(info
, str):
294 assert isinstance(info
, tuple)
299 callable, args
= info
[:2]
305 args
= deepcopy(args
, memo
)
309 state
= deepcopy(state
, memo
)
310 if hasattr(y
, '__setstate__'):
311 y
.__setstate
__(state
)
313 y
.__dict
__.update(state
)
320 # Helper for instance creation without calling __init__
325 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
326 {'abc': 'ABC'}, (), [], {}]
334 def __init__(self
, arg
=None):
337 if __name__
== '__main__':
344 def __getstate__(self
):
345 return {'a': self
.a
, 'arg': self
.arg
}
346 def __setstate__(self
, state
):
347 for key
, value
in state
.iteritems():
348 setattr(self
, key
, value
)
349 def __deepcopy__(self
, memo
= None):
350 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
353 c
= C('argument sketch')
363 l
.append({l
[1]: l
, 'xyz': l
[2]})
366 print map(repr.repr, l
)
367 print map(repr.repr, l1
)
368 print map(repr.repr, l2
)
369 print map(repr.repr, l3
)
372 print map(repr.repr, l
)
373 print map(repr.repr, l1
)
374 print map(repr.repr, l2
)
375 print map(repr.repr, l3
)
377 if __name__
== '__main__':