Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 409780f

Browse files
committed
shallow and deep copy operations
1 parent a48061a commit 409780f

1 file changed

Lines changed: 240 additions & 0 deletions

File tree

Lib/copy.py

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# 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+
35+
import types
36+
37+
Error = 'copy.Error'
38+
39+
def 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+
54+
def _copy_atomic(x):
55+
return x
56+
d[types.NoneType] = _copy_atomic
57+
d[types.IntType] = _copy_atomic
58+
d[types.LongType] = _copy_atomic
59+
d[types.FloatType] = _copy_atomic
60+
d[types.StringType] = _copy_atomic
61+
d[types.CodeType] = _copy_atomic
62+
d[types.TypeType] = _copy_atomic
63+
d[types.XRangeType] = _copy_atomic
64+
65+
def _copy_list(x):
66+
return x[:]
67+
d[types.ListType] = _copy_list
68+
69+
def _copy_tuple(x):
70+
return x[:]
71+
d[types.TupleType] = _copy_tuple
72+
73+
def _copy_dict(x):
74+
y = {}
75+
for key in x.keys():
76+
y[key] = x[key]
77+
return y
78+
d[types.DictionaryType] = _copy_dict
79+
80+
def _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
98+
d[types.InstanceType] = _copy_inst
99+
100+
del d
101+
102+
def 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+
123+
def _deepcopy_atomic(x, memo):
124+
return x
125+
d[types.NoneType] = _deepcopy_atomic
126+
d[types.IntType] = _deepcopy_atomic
127+
d[types.LongType] = _deepcopy_atomic
128+
d[types.FloatType] = _deepcopy_atomic
129+
d[types.StringType] = _deepcopy_atomic
130+
d[types.CodeType] = _deepcopy_atomic
131+
d[types.TypeType] = _deepcopy_atomic
132+
d[types.XRangeType] = _deepcopy_atomic
133+
134+
def _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
140+
d[types.ListType] = _deepcopy_list
141+
142+
def _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
155+
d[types.TupleType] = _deepcopy_tuple
156+
157+
def _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
163+
d[types.DictionaryType] = _deepcopy_dict
164+
165+
def _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
186+
d[types.InstanceType] = _deepcopy_inst
187+
188+
del d
189+
190+
del types
191+
192+
def _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+
239+
if __name__ == '__main__':
240+
_test()

0 commit comments

Comments
 (0)