blob: fe4c4fb4b8dda8ef9d140c285c8972b61e56a2a1 [file] [log] [blame]
Guido van Rossum409780f1995-01-10 00:34:21 +00001# Generic (shallow and deep) copying operations
2# =============================================
3#
4# The difference between shallow and deep copying is only relevant for
5# compound objects (objects that contain other objects, like lists or class
6# instances).
7#
8# - A shallow copy constructs a new compound object and then (to the extent
9# possible) inserts *the same objects* into in that the original contains.
10#
11# - A deep copy constructs a new compound object and then, recursively,
12# inserts *copies* into it of the objects found in the original.
13#
14# Two problems often exist with deep copy operations that don't exist with
15# shallow copy operations:
16#
17# (a) recursive objects (compound objects that, directly or indirectly,
18# contain a reference to themselves) may cause a recursive loop
19#
20# (b) because deep copy copies *everything* it may copy too much, e.g.
21# administrative data structures that should be shared even between copies
22#
23# Python's deep copy operation avoids these problems by:
24#
25# (a) keeping a table of objects already copied during the current copying pass
26#
27# (b) letting user-defined classes override the copying operation or the set
28# of components copied
29#
30# This version does not copy types like module, class, function, method,
31# nor stack trace, stack frame, nor file, socket, window, nor array,
32# nor any similar types.
33
34
35import types
36
37Error = 'copy.Error'
38
39def copy(x):
40 try:
41 copierfunction = _copy_dispatch[type(x)]
42 except KeyError:
43 try:
44 copier = x.__copy__
45 except AttributeError:
46 raise Error, "un(shallow)copyable object of type %s" % type(x)
47 y = copier()
48 else:
49 y = copierfunction(x)
50 return y
51
52_copy_dispatch = d = {}
53
54def _copy_atomic(x):
55 return x
56d[types.NoneType] = _copy_atomic
57d[types.IntType] = _copy_atomic
58d[types.LongType] = _copy_atomic
59d[types.FloatType] = _copy_atomic
60d[types.StringType] = _copy_atomic
61d[types.CodeType] = _copy_atomic
62d[types.TypeType] = _copy_atomic
63d[types.XRangeType] = _copy_atomic
64
65def _copy_list(x):
66 return x[:]
67d[types.ListType] = _copy_list
68
69def _copy_tuple(x):
70 return x[:]
71d[types.TupleType] = _copy_tuple
72
73def _copy_dict(x):
74 y = {}
75 for key in x.keys():
76 y[key] = x[key]
77 return y
78d[types.DictionaryType] = _copy_dict
79
80def _copy_inst(x):
81 if hasattr(x, '__copy__'):
82 return x.__copy__()
83 if hasattr(x, '__getinitargs__'):
84 args = x.__getinitargs__()
85 else:
86 args = ()
87 y = apply(x.__class__, args)
88 if hasattr(x, '__getstate__'):
89 state = x.__getstate__()
90 else:
91 state = x.__dict__
92 if y.hasattr('__setstate__'):
93 y.__setstate__(state)
94 else:
95 for key in state.keys():
96 setattr(y, key, state[key])
97 return y
98d[types.InstanceType] = _copy_inst
99
100del d
101
102def deepcopy(x, memo = None):
103 if memo is None:
104 memo = {}
105 d = id(x)
106 if memo.has_key(d):
107 return memo[d]
108 try:
109 copierfunction = _deepcopy_dispatch[type(x)]
110 except KeyError:
111 try:
112 copier = x.__deepcopy__
113 except AttributeError:
114 raise Error, "un-deep-copyable object of type %s" % type(x)
115 y = copier(memo)
116 else:
117 y = copierfunction(x, memo)
118 memo[d] = y
119 return y
120
121_deepcopy_dispatch = d = {}
122
123def _deepcopy_atomic(x, memo):
124 return x
125d[types.NoneType] = _deepcopy_atomic
126d[types.IntType] = _deepcopy_atomic
127d[types.LongType] = _deepcopy_atomic
128d[types.FloatType] = _deepcopy_atomic
129d[types.StringType] = _deepcopy_atomic
130d[types.CodeType] = _deepcopy_atomic
131d[types.TypeType] = _deepcopy_atomic
132d[types.XRangeType] = _deepcopy_atomic
133
134def _deepcopy_list(x, memo):
135 y = []
136 memo[id(x)] = y
137 for a in x:
138 y.append(deepcopy(a, memo))
139 return y
140d[types.ListType] = _deepcopy_list
141
142def _deepcopy_tuple(x, memo):
143 y = []
144 for a in x:
145 y.append(deepcopy(a, memo))
146 d = id(x)
147 try:
148 return memo[d]
149 except KeyError:
150 pass
151 for i in range(len(x)):
152 if x[i] is not y[i]:
153 return tuple(y)
154 return x
155d[types.TupleType] = _deepcopy_tuple
156
157def _deepcopy_dict(x, memo):
158 y = {}
159 memo[id(x)] = y
160 for key in x.keys():
161 y[deepcopy(key, memo)] = deepcopy(x[key], memo)
162 return y
163d[types.DictionaryType] = _deepcopy_dict
164
165def _deepcopy_inst(x, memo):
166 if hasattr(x, '__deepcopy__'):
167 return x.__deepcopy__()
168 if hasattr(x, '__getinitargs__'):
169 args = x.__getinitargs__()
170 args = deepcopy(args, memo)
171 else:
172 args = ()
173 y = apply(x.__class__, args)
174 memo[id(x)] = y
175 if hasattr(x, '__getstate__'):
176 state = x.__getstate__()
177 else:
178 state = x.__dict__
179 state = deepcopy(state, memo)
180 if y.hasattr('__setstate__'):
181 y.__setstate__(state)
182 else:
183 for key in state.keys():
184 setattr(y, key, state[key])
185 return y
186d[types.InstanceType] = _deepcopy_inst
187
188del d
189
190del types
191
192def _test():
193 l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'], {'abc': 'ABC'}, (), [], {}]
194 l1 = copy(l)
195 print l1==l
196 l1 = map(copy, l)
197 print l1==l
198 l1 = deepcopy(l)
199 print l1==l
200 class C:
201 def __init__(self, arg=None):
202 self.a = 1
203 self.arg = arg
204 self.fp = open('copy.py')
205 self.fp.close()
206 def __getstate__(self):
207 return {'a': self.a, 'arg': self.arg}
208 def __setstate__(self, state):
209 for key in state.keys():
210 setattr(self, key, state[key])
211 def __deepcopy__(self, memo = None):
212 new = self.__class__(deepcopy(self.arg, memo))
213 new.a = self.a
214 return new
215 c = C('argument sketch')
216 l.append(c)
217 l2 = copy(l)
218 print l == l2
219 print l
220 print l2
221 l2 = deepcopy(l)
222 print l == l2
223 print l
224 print l2
225 l.append({l[1]: l, 'xyz': l[2]})
226 l3 = copy(l)
227 import repr
228 print map(repr.repr, l)
229 print map(repr.repr, l1)
230 print map(repr.repr, l2)
231 print map(repr.repr, l3)
232 l3 = deepcopy(l)
233 import repr
234 print map(repr.repr, l)
235 print map(repr.repr, l1)
236 print map(repr.repr, l2)
237 print map(repr.repr, l3)
238
239if __name__ == '__main__':
240 _test()