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 "un(shallow)copyable object of type %s" % type(x
)
85 _copy_dispatch
= d
= {}
89 d
[types
.NoneType
] = _copy_atomic
90 d
[types
.IntType
] = _copy_atomic
91 d
[types
.LongType
] = _copy_atomic
92 d
[types
.FloatType
] = _copy_atomic
93 d
[types
.StringType
] = _copy_atomic
94 d
[types
.UnicodeType
] = _copy_atomic
96 d
[types
.CodeType
] = _copy_atomic
97 except AttributeError:
99 d
[types
.TypeType
] = _copy_atomic
100 d
[types
.XRangeType
] = _copy_atomic
101 d
[types
.ClassType
] = _copy_atomic
105 d
[types
.ListType
] = _copy_list
109 d
[types
.TupleType
] = _copy_tuple
113 d
[types
.DictionaryType
] = _copy_dict
114 if PyStringMap
is not None:
115 d
[PyStringMap
] = _copy_dict
118 if hasattr(x
, '__copy__'):
120 if hasattr(x
, '__getinitargs__'):
121 args
= x
.__getinitargs
__()
122 y
= apply(x
.__class
__, args
)
125 y
.__class
__ = x
.__class
__
126 if hasattr(x
, '__getstate__'):
127 state
= x
.__getstate
__()
130 if hasattr(y
, '__setstate__'):
131 y
.__setstate
__(state
)
133 y
.__dict
__.update(state
)
135 d
[types
.InstanceType
] = _copy_inst
139 def deepcopy(x
, memo
= None):
140 """Deep copy operation on arbitrary Python objects.
142 See the module's __doc__ string for more info.
151 copierfunction
= _deepcopy_dispatch
[type(x
)]
154 copier
= x
.__deepcopy
__
155 except AttributeError:
157 "un-deep-copyable object of type %s" % type(x
)
160 y
= copierfunction(x
, memo
)
164 _deepcopy_dispatch
= d
= {}
166 def _deepcopy_atomic(x
, memo
):
168 d
[types
.NoneType
] = _deepcopy_atomic
169 d
[types
.IntType
] = _deepcopy_atomic
170 d
[types
.LongType
] = _deepcopy_atomic
171 d
[types
.FloatType
] = _deepcopy_atomic
172 d
[types
.StringType
] = _deepcopy_atomic
173 d
[types
.UnicodeType
] = _deepcopy_atomic
174 d
[types
.CodeType
] = _deepcopy_atomic
175 d
[types
.TypeType
] = _deepcopy_atomic
176 d
[types
.XRangeType
] = _deepcopy_atomic
178 def _deepcopy_list(x
, memo
):
182 y
.append(deepcopy(a
, memo
))
184 d
[types
.ListType
] = _deepcopy_list
186 def _deepcopy_tuple(x
, memo
):
189 y
.append(deepcopy(a
, memo
))
195 for i
in range(len(x
)):
203 d
[types
.TupleType
] = _deepcopy_tuple
205 def _deepcopy_dict(x
, memo
):
209 y
[deepcopy(key
, memo
)] = deepcopy(x
[key
], memo
)
211 d
[types
.DictionaryType
] = _deepcopy_dict
212 if PyStringMap
is not None:
213 d
[PyStringMap
] = _deepcopy_dict
215 def _keep_alive(x
, memo
):
216 """Keeps a reference to the object x in the memo.
218 Because we remember objects by their id, we have
219 to assure that possibly temporary objects are kept
220 alive by referencing them.
221 We store a reference at the id of the memo, which should
222 normally not be used unless someone tries to deepcopy
226 memo
[id(memo
)].append(x
)
228 # aha, this is the first one :-)
231 def _deepcopy_inst(x
, memo
):
232 if hasattr(x
, '__deepcopy__'):
233 return x
.__deepcopy
__(memo
)
234 if hasattr(x
, '__getinitargs__'):
235 args
= x
.__getinitargs
__()
236 _keep_alive(args
, memo
)
237 args
= deepcopy(args
, memo
)
238 y
= apply(x
.__class
__, args
)
241 y
.__class
__ = x
.__class
__
243 if hasattr(x
, '__getstate__'):
244 state
= x
.__getstate
__()
245 _keep_alive(state
, memo
)
248 state
= deepcopy(state
, memo
)
249 if hasattr(y
, '__setstate__'):
250 y
.__setstate
__(state
)
252 y
.__dict
__.update(state
)
254 d
[types
.InstanceType
] = _deepcopy_inst
260 # Helper for instance creation without calling __init__
265 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
266 {'abc': 'ABC'}, (), [], {}]
274 def __init__(self
, arg
=None):
277 if __name__
== '__main__':
284 def __getstate__(self
):
285 return {'a': self
.a
, 'arg': self
.arg
}
286 def __setstate__(self
, state
):
287 for key
in state
.keys():
288 setattr(self
, key
, state
[key
])
289 def __deepcopy__(self
, memo
= None):
290 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
293 c
= C('argument sketch')
303 l
.append({l
[1]: l
, 'xyz': l
[2]})
306 print map(repr.repr, l
)
307 print map(repr.repr, l1
)
308 print map(repr.repr, l2
)
309 print map(repr.repr, l3
)
312 print map(repr.repr, l
)
313 print map(repr.repr, l1
)
314 print map(repr.repr, l2
)
315 print map(repr.repr, l3
)
317 if __name__
== '__main__':