blob: 15e0e40ad44135baac416a394eb866c3704d6f8c [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
28(a) recursive objects (compound objects that, directly or indirectly,
29 contain a reference to themselves) may cause a recursive loop
30
31(b) because deep copy copies *everything* it may copy too much, e.g.
32 administrative data structures that should be shared even between
33 copies
34
35Python's deep copy operation avoids these problems by:
36
37(a) keeping a table of objects already copied during the current
38copying pass
39
40(b) letting user-defined classes override the copying operation or the
41 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):
100 y = {}
101 for key in x.keys():
102 y[key] = x[key]
103 return y
104d[types.DictionaryType] = _copy_dict
105
106def _copy_inst(x):
107 if hasattr(x, '__copy__'):
108 return x.__copy__()
109 if hasattr(x, '__getinitargs__'):
110 args = x.__getinitargs__()
111 else:
112 args = ()
113 y = apply(x.__class__, args)
114 if hasattr(x, '__getstate__'):
115 state = x.__getstate__()
116 else:
117 state = x.__dict__
Guido van Rossumfefbbe51995-03-22 10:10:31 +0000118 if hasattr(y, '__setstate__'):
Guido van Rossum409780f1995-01-10 00:34:21 +0000119 y.__setstate__(state)
120 else:
121 for key in state.keys():
122 setattr(y, key, state[key])
123 return y
124d[types.InstanceType] = _copy_inst
125
126del d
127
128def deepcopy(x, memo = None):
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000129 """Deep copy operation on arbitrary Python objects.
130
131 See the module's __doc__ string for more info.
132 """
133
Guido van Rossum409780f1995-01-10 00:34:21 +0000134 if memo is None:
135 memo = {}
136 d = id(x)
137 if memo.has_key(d):
138 return memo[d]
139 try:
140 copierfunction = _deepcopy_dispatch[type(x)]
141 except KeyError:
142 try:
143 copier = x.__deepcopy__
144 except AttributeError:
Guido van Rossum55d2f391995-03-14 17:41:36 +0000145 raise error, \
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000146 "un-deep-copyable object of type %s" % type(x)
Guido van Rossum409780f1995-01-10 00:34:21 +0000147 y = copier(memo)
148 else:
149 y = copierfunction(x, memo)
150 memo[d] = y
151 return y
152
153_deepcopy_dispatch = d = {}
154
155def _deepcopy_atomic(x, memo):
156 return x
157d[types.NoneType] = _deepcopy_atomic
158d[types.IntType] = _deepcopy_atomic
159d[types.LongType] = _deepcopy_atomic
160d[types.FloatType] = _deepcopy_atomic
161d[types.StringType] = _deepcopy_atomic
162d[types.CodeType] = _deepcopy_atomic
163d[types.TypeType] = _deepcopy_atomic
164d[types.XRangeType] = _deepcopy_atomic
165
166def _deepcopy_list(x, memo):
167 y = []
168 memo[id(x)] = y
169 for a in x:
170 y.append(deepcopy(a, memo))
171 return y
172d[types.ListType] = _deepcopy_list
173
174def _deepcopy_tuple(x, memo):
175 y = []
176 for a in x:
177 y.append(deepcopy(a, memo))
178 d = id(x)
179 try:
180 return memo[d]
181 except KeyError:
182 pass
183 for i in range(len(x)):
184 if x[i] is not y[i]:
Guido van Rossum6afff611996-06-17 17:10:11 +0000185 y = tuple(y)
186 break
187 else:
188 y = x
189 memo[d] = y
190 return y
Guido van Rossum409780f1995-01-10 00:34:21 +0000191d[types.TupleType] = _deepcopy_tuple
192
193def _deepcopy_dict(x, memo):
194 y = {}
195 memo[id(x)] = y
196 for key in x.keys():
197 y[deepcopy(key, memo)] = deepcopy(x[key], memo)
198 return y
199d[types.DictionaryType] = _deepcopy_dict
200
201def _deepcopy_inst(x, memo):
202 if hasattr(x, '__deepcopy__'):
203 return x.__deepcopy__()
204 if hasattr(x, '__getinitargs__'):
205 args = x.__getinitargs__()
206 args = deepcopy(args, memo)
207 else:
208 args = ()
209 y = apply(x.__class__, args)
210 memo[id(x)] = y
211 if hasattr(x, '__getstate__'):
212 state = x.__getstate__()
213 else:
214 state = x.__dict__
215 state = deepcopy(state, memo)
Guido van Rossumfefbbe51995-03-22 10:10:31 +0000216 if hasattr(y, '__setstate__'):
Guido van Rossum409780f1995-01-10 00:34:21 +0000217 y.__setstate__(state)
218 else:
219 for key in state.keys():
220 setattr(y, key, state[key])
221 return y
222d[types.InstanceType] = _deepcopy_inst
223
224del d
225
226del types
227
228def _test():
Guido van Rossum55d2f391995-03-14 17:41:36 +0000229 l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
230 {'abc': 'ABC'}, (), [], {}]
Guido van Rossum409780f1995-01-10 00:34:21 +0000231 l1 = copy(l)
232 print l1==l
233 l1 = map(copy, l)
234 print l1==l
235 l1 = deepcopy(l)
236 print l1==l
237 class C:
238 def __init__(self, arg=None):
239 self.a = 1
240 self.arg = arg
241 self.fp = open('copy.py')
242 self.fp.close()
243 def __getstate__(self):
244 return {'a': self.a, 'arg': self.arg}
245 def __setstate__(self, state):
246 for key in state.keys():
247 setattr(self, key, state[key])
248 def __deepcopy__(self, memo = None):
249 new = self.__class__(deepcopy(self.arg, memo))
250 new.a = self.a
251 return new
252 c = C('argument sketch')
253 l.append(c)
254 l2 = copy(l)
255 print l == l2
256 print l
257 print l2
258 l2 = deepcopy(l)
259 print l == l2
260 print l
261 print l2
262 l.append({l[1]: l, 'xyz': l[2]})
263 l3 = copy(l)
264 import repr
265 print map(repr.repr, l)
266 print map(repr.repr, l1)
267 print map(repr.repr, l2)
268 print map(repr.repr, l3)
269 l3 = deepcopy(l)
270 import repr
271 print map(repr.repr, l)
272 print map(repr.repr, l1)
273 print map(repr.repr, l2)
274 print map(repr.repr, l3)
275
276if __name__ == '__main__':
277 _test()