blob: 6dc781c4e06a1ffe509abffe13fbb212c5409760 [file] [log] [blame]
Guido van Rossumcc6764c1995-02-09 17:18:10 +00001"""\
2Generic (shallow and deep) copying operations
3=============================================
Guido van Rossum409780f1995-01-10 00:34:21 +00004
Guido van Rossumcc6764c1995-02-09 17:18:10 +00005Interface summary:
6
7 import copy
8
9 x = copy.copy(y) # make a shallow copy of y
10 x = copy.deepcopy(y) # make a deep copy of y
11
Guido van Rossum55d2f391995-03-14 17:41:36 +000012For module specific errors, copy.error is raised.
Guido van Rossumcc6764c1995-02-09 17:18:10 +000013
14The difference between shallow and deep copying is only relevant for
15compound objects (objects that contain other objects, like lists or
16class instances).
17
18- A shallow copy constructs a new compound object and then (to the
19 extent possible) inserts *the same objects* into in that the
20 original contains.
21
22- A deep copy constructs a new compound object and then, recursively,
23 inserts *copies* into it of the objects found in the original.
24
25Two problems often exist with deep copy operations that don't exist
26with shallow copy operations:
27
Guido van Rossumf7cea101997-05-28 19:31:14 +000028 a) recursive objects (compound objects that, directly or indirectly,
Guido van Rossumcc6764c1995-02-09 17:18:10 +000029 contain a reference to themselves) may cause a recursive loop
30
Guido van Rossumf7cea101997-05-28 19:31:14 +000031 b) because deep copy copies *everything* it may copy too much, e.g.
Guido van Rossumcc6764c1995-02-09 17:18:10 +000032 administrative data structures that should be shared even between
33 copies
34
35Python's deep copy operation avoids these problems by:
36
Guido van Rossumf7cea101997-05-28 19:31:14 +000037 a) keeping a table of objects already copied during the current
38 copying pass
Guido van Rossumcc6764c1995-02-09 17:18:10 +000039
Guido van Rossumf7cea101997-05-28 19:31:14 +000040 b) letting user-defined classes override the copying operation or the
Guido van Rossumcc6764c1995-02-09 17:18:10 +000041 set of components copied
42
43This version does not copy types like module, class, function, method,
44nor stack trace, stack frame, nor file, socket, window, nor array, nor
45any similar types.
46
47Classes can use the same interfaces to control copying that they use
48to 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.
51"""
Guido van Rossum409780f1995-01-10 00:34:21 +000052
53import types
54
Guido van Rossum55d2f391995-03-14 17:41:36 +000055error = 'copy.error'
56Error = error # backward compatibility
Guido van Rossum409780f1995-01-10 00:34:21 +000057
58def copy(x):
Guido van Rossumcc6764c1995-02-09 17:18:10 +000059 """Shallow copy operation on arbitrary Python objects.
60
61 See the module's __doc__ string for more info.
62 """
63
Guido van Rossum409780f1995-01-10 00:34:21 +000064 try:
65 copierfunction = _copy_dispatch[type(x)]
66 except KeyError:
67 try:
68 copier = x.__copy__
69 except AttributeError:
Guido van Rossum55d2f391995-03-14 17:41:36 +000070 raise error, \
Guido van Rossumcc6764c1995-02-09 17:18:10 +000071 "un(shallow)copyable object of type %s" % type(x)
Guido van Rossum409780f1995-01-10 00:34:21 +000072 y = copier()
73 else:
74 y = copierfunction(x)
75 return y
76
77_copy_dispatch = d = {}
78
79def _copy_atomic(x):
80 return x
81d[types.NoneType] = _copy_atomic
82d[types.IntType] = _copy_atomic
83d[types.LongType] = _copy_atomic
84d[types.FloatType] = _copy_atomic
85d[types.StringType] = _copy_atomic
86d[types.CodeType] = _copy_atomic
87d[types.TypeType] = _copy_atomic
88d[types.XRangeType] = _copy_atomic
Guido van Rossum55d2f391995-03-14 17:41:36 +000089d[types.ClassType] = _copy_atomic
Guido van Rossum409780f1995-01-10 00:34:21 +000090
91def _copy_list(x):
92 return x[:]
93d[types.ListType] = _copy_list
94
95def _copy_tuple(x):
96 return x[:]
97d[types.TupleType] = _copy_tuple
98
99def _copy_dict(x):
Guido van Rossumf7cea101997-05-28 19:31:14 +0000100 return x.copy()
Guido van Rossum409780f1995-01-10 00:34:21 +0000101d[types.DictionaryType] = _copy_dict
102
103def _copy_inst(x):
104 if hasattr(x, '__copy__'):
105 return x.__copy__()
106 if hasattr(x, '__getinitargs__'):
107 args = x.__getinitargs__()
108 else:
109 args = ()
110 y = apply(x.__class__, args)
111 if hasattr(x, '__getstate__'):
112 state = x.__getstate__()
113 else:
114 state = x.__dict__
Guido van Rossumfefbbe51995-03-22 10:10:31 +0000115 if hasattr(y, '__setstate__'):
Guido van Rossum409780f1995-01-10 00:34:21 +0000116 y.__setstate__(state)
117 else:
118 for key in state.keys():
119 setattr(y, key, state[key])
120 return y
121d[types.InstanceType] = _copy_inst
122
123del d
124
125def deepcopy(x, memo = None):
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000126 """Deep copy operation on arbitrary Python objects.
127
128 See the module's __doc__ string for more info.
129 """
130
Guido van Rossum409780f1995-01-10 00:34:21 +0000131 if memo is None:
132 memo = {}
133 d = id(x)
134 if memo.has_key(d):
135 return memo[d]
136 try:
137 copierfunction = _deepcopy_dispatch[type(x)]
138 except KeyError:
139 try:
140 copier = x.__deepcopy__
141 except AttributeError:
Guido van Rossum55d2f391995-03-14 17:41:36 +0000142 raise error, \
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000143 "un-deep-copyable object of type %s" % type(x)
Guido van Rossum409780f1995-01-10 00:34:21 +0000144 y = copier(memo)
145 else:
146 y = copierfunction(x, memo)
147 memo[d] = y
148 return y
149
150_deepcopy_dispatch = d = {}
151
152def _deepcopy_atomic(x, memo):
153 return x
154d[types.NoneType] = _deepcopy_atomic
155d[types.IntType] = _deepcopy_atomic
156d[types.LongType] = _deepcopy_atomic
157d[types.FloatType] = _deepcopy_atomic
158d[types.StringType] = _deepcopy_atomic
159d[types.CodeType] = _deepcopy_atomic
160d[types.TypeType] = _deepcopy_atomic
161d[types.XRangeType] = _deepcopy_atomic
162
163def _deepcopy_list(x, memo):
164 y = []
165 memo[id(x)] = y
166 for a in x:
167 y.append(deepcopy(a, memo))
168 return y
169d[types.ListType] = _deepcopy_list
170
171def _deepcopy_tuple(x, memo):
172 y = []
173 for a in x:
174 y.append(deepcopy(a, memo))
175 d = id(x)
176 try:
177 return memo[d]
178 except KeyError:
179 pass
180 for i in range(len(x)):
181 if x[i] is not y[i]:
Guido van Rossum6afff611996-06-17 17:10:11 +0000182 y = tuple(y)
183 break
184 else:
185 y = x
186 memo[d] = y
187 return y
Guido van Rossum409780f1995-01-10 00:34:21 +0000188d[types.TupleType] = _deepcopy_tuple
189
190def _deepcopy_dict(x, memo):
191 y = {}
192 memo[id(x)] = y
193 for key in x.keys():
194 y[deepcopy(key, memo)] = deepcopy(x[key], memo)
195 return y
196d[types.DictionaryType] = _deepcopy_dict
197
198def _deepcopy_inst(x, memo):
199 if hasattr(x, '__deepcopy__'):
200 return x.__deepcopy__()
201 if hasattr(x, '__getinitargs__'):
202 args = x.__getinitargs__()
203 args = deepcopy(args, memo)
204 else:
205 args = ()
206 y = apply(x.__class__, args)
207 memo[id(x)] = y
208 if hasattr(x, '__getstate__'):
209 state = x.__getstate__()
210 else:
211 state = x.__dict__
212 state = deepcopy(state, memo)
Guido van Rossumfefbbe51995-03-22 10:10:31 +0000213 if hasattr(y, '__setstate__'):
Guido van Rossum409780f1995-01-10 00:34:21 +0000214 y.__setstate__(state)
215 else:
216 for key in state.keys():
217 setattr(y, key, state[key])
218 return y
219d[types.InstanceType] = _deepcopy_inst
220
221del d
222
223del types
224
225def _test():
Guido van Rossum55d2f391995-03-14 17:41:36 +0000226 l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
227 {'abc': 'ABC'}, (), [], {}]
Guido van Rossum409780f1995-01-10 00:34:21 +0000228 l1 = copy(l)
229 print l1==l
230 l1 = map(copy, l)
231 print l1==l
232 l1 = deepcopy(l)
233 print l1==l
234 class C:
235 def __init__(self, arg=None):
236 self.a = 1
237 self.arg = arg
Guido van Rossumf7cea101997-05-28 19:31:14 +0000238 if __name__ == '__main__':
239 import sys
240 file = sys.argv[0]
241 else:
242 file = __file__
243 self.fp = open(file)
Guido van Rossum409780f1995-01-10 00:34:21 +0000244 self.fp.close()
245 def __getstate__(self):
246 return {'a': self.a, 'arg': self.arg}
247 def __setstate__(self, state):
248 for key in state.keys():
249 setattr(self, key, state[key])
250 def __deepcopy__(self, memo = None):
251 new = self.__class__(deepcopy(self.arg, memo))
252 new.a = self.a
253 return new
254 c = C('argument sketch')
255 l.append(c)
256 l2 = copy(l)
257 print l == l2
258 print l
259 print l2
260 l2 = deepcopy(l)
261 print l == l2
262 print l
263 print l2
264 l.append({l[1]: l, 'xyz': l[2]})
265 l3 = copy(l)
266 import repr
267 print map(repr.repr, l)
268 print map(repr.repr, l1)
269 print map(repr.repr, l2)
270 print map(repr.repr, l3)
271 l3 = deepcopy(l)
272 import repr
273 print map(repr.repr, l)
274 print map(repr.repr, l1)
275 print map(repr.repr, l2)
276 print map(repr.repr, l3)
277
278if __name__ == '__main__':
279 _test()