blob: 966bfa2c0b760b23f798a70b15e3afe727a72ddc [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
12For module specific errors, copy.Error is raised.
13
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
55Error = 'copy.Error'
56
57def copy(x):
Guido van Rossumcc6764c1995-02-09 17:18:10 +000058 """Shallow copy operation on arbitrary Python objects.
59
60 See the module's __doc__ string for more info.
61 """
62
Guido van Rossum409780f1995-01-10 00:34:21 +000063 try:
64 copierfunction = _copy_dispatch[type(x)]
65 except KeyError:
66 try:
67 copier = x.__copy__
68 except AttributeError:
Guido van Rossumcc6764c1995-02-09 17:18:10 +000069 raise Error, \
70 "un(shallow)copyable object of type %s" % type(x)
Guido van Rossum409780f1995-01-10 00:34:21 +000071 y = copier()
72 else:
73 y = copierfunction(x)
74 return y
75
76_copy_dispatch = d = {}
77
78def _copy_atomic(x):
79 return x
80d[types.NoneType] = _copy_atomic
81d[types.IntType] = _copy_atomic
82d[types.LongType] = _copy_atomic
83d[types.FloatType] = _copy_atomic
84d[types.StringType] = _copy_atomic
85d[types.CodeType] = _copy_atomic
86d[types.TypeType] = _copy_atomic
87d[types.XRangeType] = _copy_atomic
88
89def _copy_list(x):
90 return x[:]
91d[types.ListType] = _copy_list
92
93def _copy_tuple(x):
94 return x[:]
95d[types.TupleType] = _copy_tuple
96
97def _copy_dict(x):
98 y = {}
99 for key in x.keys():
100 y[key] = x[key]
101 return y
102d[types.DictionaryType] = _copy_dict
103
104def _copy_inst(x):
105 if hasattr(x, '__copy__'):
106 return x.__copy__()
107 if hasattr(x, '__getinitargs__'):
108 args = x.__getinitargs__()
109 else:
110 args = ()
111 y = apply(x.__class__, args)
112 if hasattr(x, '__getstate__'):
113 state = x.__getstate__()
114 else:
115 state = x.__dict__
116 if y.hasattr('__setstate__'):
117 y.__setstate__(state)
118 else:
119 for key in state.keys():
120 setattr(y, key, state[key])
121 return y
122d[types.InstanceType] = _copy_inst
123
124del d
125
126def deepcopy(x, memo = None):
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000127 """Deep copy operation on arbitrary Python objects.
128
129 See the module's __doc__ string for more info.
130 """
131
Guido van Rossum409780f1995-01-10 00:34:21 +0000132 if memo is None:
133 memo = {}
134 d = id(x)
135 if memo.has_key(d):
136 return memo[d]
137 try:
138 copierfunction = _deepcopy_dispatch[type(x)]
139 except KeyError:
140 try:
141 copier = x.__deepcopy__
142 except AttributeError:
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000143 raise Error, \
144 "un-deep-copyable object of type %s" % type(x)
Guido van Rossum409780f1995-01-10 00:34:21 +0000145 y = copier(memo)
146 else:
147 y = copierfunction(x, memo)
148 memo[d] = y
149 return y
150
151_deepcopy_dispatch = d = {}
152
153def _deepcopy_atomic(x, memo):
154 return x
155d[types.NoneType] = _deepcopy_atomic
156d[types.IntType] = _deepcopy_atomic
157d[types.LongType] = _deepcopy_atomic
158d[types.FloatType] = _deepcopy_atomic
159d[types.StringType] = _deepcopy_atomic
160d[types.CodeType] = _deepcopy_atomic
161d[types.TypeType] = _deepcopy_atomic
162d[types.XRangeType] = _deepcopy_atomic
163
164def _deepcopy_list(x, memo):
165 y = []
166 memo[id(x)] = y
167 for a in x:
168 y.append(deepcopy(a, memo))
169 return y
170d[types.ListType] = _deepcopy_list
171
172def _deepcopy_tuple(x, memo):
173 y = []
174 for a in x:
175 y.append(deepcopy(a, memo))
176 d = id(x)
177 try:
178 return memo[d]
179 except KeyError:
180 pass
181 for i in range(len(x)):
182 if x[i] is not y[i]:
183 return tuple(y)
184 return x
185d[types.TupleType] = _deepcopy_tuple
186
187def _deepcopy_dict(x, memo):
188 y = {}
189 memo[id(x)] = y
190 for key in x.keys():
191 y[deepcopy(key, memo)] = deepcopy(x[key], memo)
192 return y
193d[types.DictionaryType] = _deepcopy_dict
194
195def _deepcopy_inst(x, memo):
196 if hasattr(x, '__deepcopy__'):
197 return x.__deepcopy__()
198 if hasattr(x, '__getinitargs__'):
199 args = x.__getinitargs__()
200 args = deepcopy(args, memo)
201 else:
202 args = ()
203 y = apply(x.__class__, args)
204 memo[id(x)] = y
205 if hasattr(x, '__getstate__'):
206 state = x.__getstate__()
207 else:
208 state = x.__dict__
209 state = deepcopy(state, memo)
210 if y.hasattr('__setstate__'):
211 y.__setstate__(state)
212 else:
213 for key in state.keys():
214 setattr(y, key, state[key])
215 return y
216d[types.InstanceType] = _deepcopy_inst
217
218del d
219
220del types
221
222def _test():
223 l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'], {'abc': 'ABC'}, (), [], {}]
224 l1 = copy(l)
225 print l1==l
226 l1 = map(copy, l)
227 print l1==l
228 l1 = deepcopy(l)
229 print l1==l
230 class C:
231 def __init__(self, arg=None):
232 self.a = 1
233 self.arg = arg
234 self.fp = open('copy.py')
235 self.fp.close()
236 def __getstate__(self):
237 return {'a': self.a, 'arg': self.arg}
238 def __setstate__(self, state):
239 for key in state.keys():
240 setattr(self, key, state[key])
241 def __deepcopy__(self, memo = None):
242 new = self.__class__(deepcopy(self.arg, memo))
243 new.a = self.a
244 return new
245 c = C('argument sketch')
246 l.append(c)
247 l2 = copy(l)
248 print l == l2
249 print l
250 print l2
251 l2 = deepcopy(l)
252 print l == l2
253 print l
254 print l2
255 l.append({l[1]: l, 'xyz': l[2]})
256 l3 = copy(l)
257 import repr
258 print map(repr.repr, l)
259 print map(repr.repr, l1)
260 print map(repr.repr, l2)
261 print map(repr.repr, l3)
262 l3 = deepcopy(l)
263 import repr
264 print map(repr.repr, l)
265 print map(repr.repr, l1)
266 print map(repr.repr, l2)
267 print map(repr.repr, l3)
268
269if __name__ == '__main__':
270 _test()