2 Generic (shallow and deep) copying operations
3 =============================================
9 x = copy.copy(y) # make a shallow copy of y
10 x = copy.deepcopy(y) # make a deep copy of y
12 For module specific errors, copy.error is raised.
14 The difference between shallow and deep copying is only relevant for
15 compound objects (objects that contain other objects, like lists or
18 - A shallow copy constructs a new compound object and then (to the
19 extent possible) inserts *the same objects* into in that the
22 - A deep copy constructs a new compound object and then, recursively,
23 inserts *copies* into it of the objects found in the original.
25 Two problems often exist with deep copy operations that don't exist
26 with shallow copy operations:
28 (a) recursive objects (compound objects that, directly or indirectly,
29 contain a reference to themselves) may cause a recursive loop
31 (b) because deep copy copies *everything* it may copy too much, e.g.
32 administrative data structures that should be shared even between
35 Python's deep copy operation avoids these problems by:
37 (a) keeping a table of objects already copied during the current
40 (b) letting user-defined classes override the copying operation or the
41 set of components copied
43 This version does not copy types like module, class, function, method,
44 nor stack trace, stack frame, nor file, socket, window, nor array, nor
47 Classes can use the same interfaces to control copying that they use
48 to control pickling: they can define methods called __getinitargs__(),
49 __getstate__() and __setstate__(). See the __doc__ string of module
50 "pickle" for information on these methods.
56 Error
= error
# backward compatibility
59 """Shallow copy operation on arbitrary Python objects.
61 See the module's __doc__ string for more info.
65 copierfunction
= _copy_dispatch
[type(x
)]
69 except AttributeError:
71 "un(shallow)copyable object of type %s" % type(x
)
77 _copy_dispatch
= d
= {}
81 d
[types
.NoneType
] = _copy_atomic
82 d
[types
.IntType
] = _copy_atomic
83 d
[types
.LongType
] = _copy_atomic
84 d
[types
.FloatType
] = _copy_atomic
85 d
[types
.StringType
] = _copy_atomic
86 d
[types
.CodeType
] = _copy_atomic
87 d
[types
.TypeType
] = _copy_atomic
88 d
[types
.XRangeType
] = _copy_atomic
89 d
[types
.ClassType
] = _copy_atomic
93 d
[types
.ListType
] = _copy_list
97 d
[types
.TupleType
] = _copy_tuple
104 d
[types
.DictionaryType
] = _copy_dict
107 if hasattr(x
, '__copy__'):
109 if hasattr(x
, '__getinitargs__'):
110 args
= x
.__getinitargs
__()
113 y
= apply(x
.__class
__, args
)
114 if hasattr(x
, '__getstate__'):
115 state
= x
.__getstate
__()
118 if hasattr(y
, '__setstate__'):
119 y
.__setstate
__(state
)
121 for key
in state
.keys():
122 setattr(y
, key
, state
[key
])
124 d
[types
.InstanceType
] = _copy_inst
128 def deepcopy(x
, memo
= None):
129 """Deep copy operation on arbitrary Python objects.
131 See the module's __doc__ string for more info.
140 copierfunction
= _deepcopy_dispatch
[type(x
)]
143 copier
= x
.__deepcopy
__
144 except AttributeError:
146 "un-deep-copyable object of type %s" % type(x
)
149 y
= copierfunction(x
, memo
)
153 _deepcopy_dispatch
= d
= {}
155 def _deepcopy_atomic(x
, memo
):
157 d
[types
.NoneType
] = _deepcopy_atomic
158 d
[types
.IntType
] = _deepcopy_atomic
159 d
[types
.LongType
] = _deepcopy_atomic
160 d
[types
.FloatType
] = _deepcopy_atomic
161 d
[types
.StringType
] = _deepcopy_atomic
162 d
[types
.CodeType
] = _deepcopy_atomic
163 d
[types
.TypeType
] = _deepcopy_atomic
164 d
[types
.XRangeType
] = _deepcopy_atomic
166 def _deepcopy_list(x
, memo
):
170 y
.append(deepcopy(a
, memo
))
172 d
[types
.ListType
] = _deepcopy_list
174 def _deepcopy_tuple(x
, memo
):
177 y
.append(deepcopy(a
, memo
))
183 for i
in range(len(x
)):
187 d
[types
.TupleType
] = _deepcopy_tuple
189 def _deepcopy_dict(x
, memo
):
193 y
[deepcopy(key
, memo
)] = deepcopy(x
[key
], memo
)
195 d
[types
.DictionaryType
] = _deepcopy_dict
197 def _deepcopy_inst(x
, memo
):
198 if hasattr(x
, '__deepcopy__'):
199 return x
.__deepcopy
__()
200 if hasattr(x
, '__getinitargs__'):
201 args
= x
.__getinitargs
__()
202 args
= deepcopy(args
, memo
)
205 y
= apply(x
.__class
__, args
)
207 if hasattr(x
, '__getstate__'):
208 state
= x
.__getstate
__()
211 state
= deepcopy(state
, memo
)
212 if hasattr(y
, '__setstate__'):
213 y
.__setstate
__(state
)
215 for key
in state
.keys():
216 setattr(y
, key
, state
[key
])
218 d
[types
.InstanceType
] = _deepcopy_inst
225 l
= [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
226 {'abc': 'ABC'}, (), [], {}]
234 def __init__(self
, arg
=None):
237 self
.fp
= open('copy.py')
239 def __getstate__(self
):
240 return {'a': self
.a
, 'arg': self
.arg
}
241 def __setstate__(self
, state
):
242 for key
in state
.keys():
243 setattr(self
, key
, state
[key
])
244 def __deepcopy__(self
, memo
= None):
245 new
= self
.__class
__(deepcopy(self
.arg
, memo
))
248 c
= C('argument sketch')
258 l
.append({l
[1]: l
, 'xyz': l
[2]})
261 print map(repr.repr, l
)
262 print map(repr.repr, l1
)
263 print map(repr.repr, l2
)
264 print map(repr.repr, l3
)
267 print map(repr.repr, l
)
268 print map(repr.repr, l1
)
269 print map(repr.repr, l2
)
270 print map(repr.repr, l3
)
272 if __name__
== '__main__':