I have a class
- whose instances have attributes that are containers
- which themselves contain containers, each of which contains many elements
- has expensive initialization of these containers.
I want to create copies of instances so
- container attributes are copied, not separated as links, but
- the containers inside each container are not heavily copied, but are common links
- avoids calling an expensive
__init__()class method
As an example, you can use the class below SetDict, which, when creating an instance, initializes a data structure, similar to a dictionary, as an attribute d. dstores integers as keys and sets them as values.
import collections
class SetDict(object):
def __init__(self, size):
self.d = collections.defaultdict(set)
for i in range(size):
self.d[i].add(1)
I would like to copy instances SetDict, so I dcopy myself, but the sets that are its values โโare not deeply copied and instead are just references to sets.
For example, consider the following behavior for this class, where it copy.copydoes not copy the attribute dto a new copy, but copy.deepcopycreates completely new copies of the sets, which are values d.
>>> import copy
>>> s = SetDict(3)
>>> s.d
defaultdict(<type 'set'>, {0: set([1]), 1: set([1]), 2: set([1])})
>>>
>>> t = copy.copy(s)
>>>
>>> t.d[3] = set([2])
>>> t.d
defaultdict(<type 'set'>, {0: set([1]), 1: set([1]), 2: set([1]), 3: set([2])})
>>>
>>> s.d
defaultdict(<type 'set'>, {0: set([1]), 1: set([1]), 2: set([1]), 3: set([2])})
>>>
>>> s = SetDict(3)
>>>
>>> u = copy.deepcopy(s)
>>> u.d[0].add(2)
>>> u.d[0]
set([1, 2])
>>>
>>> s.d[0]
set([1])
The behavior I would like to see would be as follows:
>>> s = SetDict(3)
>>> s.d
defaultdict(<type 'set'>, {0: set([1]), 1: set([1]), 2: set([1])})
>>> t = copy.copy(s)
>>>
>>> t.d[3] = set([2])
>>> t.d
defaultdict(<type 'set'>, {0: set([1]), 1: set([1]), 2: set([1]), 3: set([2])})
>>>
>>> s.d
defaultdict(<type 'set'>, {0: set([1]), 1: set([1]), 2: set([1])})
>>> t.d[0].add(2)
>>> t.d[0]
set([1, 2])
>>>
>>> s.d[0]
set([1, 2])
, , - :
class CopiableSetDict(SetDict):
def __copy__(self):
import copy
other = copy.copy(self)
other.d = copy.copy(self.d)
return other
, copy.copy ( copy.deepcopy) . , copy.copy copy.deepcopy. ?