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.
53 from copyreg
import dispatch_table
55 class Error(Exception):
57 error
= Error
# backward compatibility
60 from org
.python
.core
import PyStringMap
64 __all__
= ["Error", "copy", "deepcopy"]
67 """Shallow copy operation on arbitrary Python objects.
69 See the module's __doc__ string for more info.
74 copier
= _copy_dispatch
.get(cls
)
78 copier
= getattr(cls
, "__copy__", None)
82 reductor
= dispatch_table
.get(cls
)
86 reductor
= getattr(x
, "__reduce_ex__", None)
90 reductor
= getattr(x
, "__reduce__", None)
94 raise Error("un(shallow)copyable object of type %s" % cls
)
96 return _reconstruct(x
, rv
, 0)
99 _copy_dispatch
= d
= {}
101 def _copy_immutable(x
):
103 for t
in (type(None), int, float, bool, str, tuple,
104 frozenset, type, range,
105 types
.BuiltinFunctionType
, type(Ellipsis),
106 types
.FunctionType
, weakref
.ref
):
107 d
[t
] = _copy_immutable
108 t
= getattr(types
, "CodeType", None)
110 d
[t
] = _copy_immutable
111 for name
in ("complex", "unicode"):
112 t
= globals()['__builtins__'].get(name
)
114 d
[t
] = _copy_immutable
116 def _copy_with_constructor(x
):
118 for t
in (list, dict, set):
119 d
[t
] = _copy_with_constructor
121 def _copy_with_copy_method(x
):
123 if PyStringMap
is not None:
124 d
[PyStringMap
] = _copy_with_copy_method
128 def deepcopy(x
, memo
=None, _nil
=[]):
129 """Deep copy operation on arbitrary Python objects.
131 See the module's __doc__ string for more info.
138 y
= memo
.get(d
, _nil
)
144 copier
= _deepcopy_dispatch
.get(cls
)
149 issc
= issubclass(cls
, type)
150 except TypeError: # cls is not a class (old Boost; see SF #502085)
153 y
= _deepcopy_atomic(x
, memo
)
155 copier
= getattr(x
, "__deepcopy__", None)
159 reductor
= dispatch_table
.get(cls
)
163 reductor
= getattr(x
, "__reduce_ex__", None)
167 reductor
= getattr(x
, "__reduce__", None)
172 "un(deep)copyable object of type %s" % cls
)
173 y
= _reconstruct(x
, rv
, 1, memo
)
176 _keep_alive(x
, memo
) # Make sure x lives at least as long as d
179 _deepcopy_dispatch
= d
= {}
181 def _deepcopy_atomic(x
, memo
):
183 d
[type(None)] = _deepcopy_atomic
184 d
[type(Ellipsis)] = _deepcopy_atomic
185 d
[int] = _deepcopy_atomic
186 d
[float] = _deepcopy_atomic
187 d
[bool] = _deepcopy_atomic
189 d
[complex] = _deepcopy_atomic
192 d
[bytes
] = _deepcopy_atomic
193 d
[str] = _deepcopy_atomic
195 d
[types
.CodeType
] = _deepcopy_atomic
196 except AttributeError:
198 d
[type] = _deepcopy_atomic
199 d
[range] = _deepcopy_atomic
200 d
[types
.BuiltinFunctionType
] = _deepcopy_atomic
201 d
[types
.FunctionType
] = _deepcopy_atomic
202 d
[weakref
.ref
] = _deepcopy_atomic
204 def _deepcopy_list(x
, memo
):
208 y
.append(deepcopy(a
, memo
))
210 d
[list] = _deepcopy_list
212 def _deepcopy_tuple(x
, memo
):
215 y
.append(deepcopy(a
, memo
))
221 for i
in range(len(x
)):
229 d
[tuple] = _deepcopy_tuple
231 def _deepcopy_dict(x
, memo
):
234 for key
, value
in x
.items():
235 y
[deepcopy(key
, memo
)] = deepcopy(value
, memo
)
237 d
[dict] = _deepcopy_dict
238 if PyStringMap
is not None:
239 d
[PyStringMap
] = _deepcopy_dict
241 def _keep_alive(x
, memo
):
242 """Keeps a reference to the object x in the memo.
244 Because we remember objects by their id, we have
245 to assure that possibly temporary objects are kept
246 alive by referencing them.
247 We store a reference at the id of the memo, which should
248 normally not be used unless someone tries to deepcopy
252 memo
[id(memo
)].append(x
)
254 # aha, this is the first one :-)
257 def _reconstruct(x
, info
, deep
, memo
=None):
258 if isinstance(info
, str):
260 assert isinstance(info
, tuple)
264 assert n
in (2, 3, 4, 5)
265 callable, args
= info
[:2]
279 args
= deepcopy(args
, memo
)
282 if listiter
is not None:
283 for item
in listiter
:
285 item
= deepcopy(item
, memo
)
287 if dictiter
is not None:
288 for key
, value
in dictiter
:
290 key
= deepcopy(key
, memo
)
291 value
= deepcopy(value
, memo
)
295 state
= deepcopy(state
, memo
)
296 if hasattr(y
, '__setstate__'):
297 y
.__setstate
__(state
)
299 if isinstance(state
, tuple) and len(state
) == 2:
300 state
, slotstate
= state
303 if state
is not None:
304 y
.__dict
__.update(state
)
305 if slotstate
is not None:
306 for key
, value
in slotstate
.items():
307 setattr(y
, key
, value
)
314 # Helper for instance creation without calling __init__
319 l
= [None, 1, 2, 3.14, 'xyzzy', (1, 2), [3.14, 'abc'],
320 {'abc': 'ABC'}, (), [], {}]
328 def __init__(self
, arg
=None):
331 if __name__
== '__main__':
338 def __getstate__(self
):
339 return {'a': self
.a
, 'arg': self
.arg
}
340 def __setstate__(self
, state
):
341 for key
, value
in state
.items():
342 setattr(self
, key
, value
)
343 def __deepcopy__(self
, memo
=None):
344 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
347 c
= C('argument sketch')
357 l
.append({l
[1]: l
, 'xyz': l
[2]})
360 print(map(reprlib
.repr, l
))
361 print(map(reprlib
.repr, l1
))
362 print(map(reprlib
.repr, l2
))
363 print(map(reprlib
.repr, l3
))
365 print(map(reprlib
.repr, l
))
366 print(map(reprlib
.repr, l1
))
367 print(map(reprlib
.repr, l2
))
368 print(map(reprlib
.repr, l3
))
370 if __name__
== '__main__':