Reputation: 145
I have a graph that is represented as a dict
where each key is an instance of a (self-defined) Node
class and the values are sets of instances of Nodes
. So, basically, the graph looks something like this, but way larger:
g = { Node1 : {Node2, Node3}, Node2 : {Node4}, Node3: set(), Node4 : {Node1} }
In very short words of what I want to do: I want to arbitrarily change a dictionary and then revert it to its original value before those changes.
I have a series of transformations that I can make to this graph, but I don't have any possible way of knowing beforehand which transformation that I want to do. The transformation will always:
Since I don't know which transformation I want to do, I want to perform every transformation to the same graph and then pick one.
An obvious idiom could be:
temp = g
)t
:
t
on the graph g
to form the graph g'
g'
for laterg = temp
to restore the graph to the known-good stateThis does not work because copying the dictionary only performs a shallow copy, so all changes to g
are also performed on temp
.
I can use deepcopy
, but even that cannot work as is. I want to deepcopy
the actual dictionary g
, but the keys and elements in the values of g
(the Nodes
) cannot be deepcopied, because in my transformation, I will look for elements that are in g
but not in temp
because they are now new objects.
I can attempt to redefine deepcopy
for the Node
class, which works, but it is very hackish and I do need to use deepcopy to perform my transformations t
.
Following is a minimal working example that does what I want it to do -- but in a way that I do not want to because then I need to create a workaround for making deepcopy actually work when I need it to. Also, the code to do the transformations is all using g
and the actual Nodes
in g
as it stands right now, so not having to change much of that would be nice.
Is there a better way to do this? (all print
s should be True
)
from copy import deepcopy
class MyClass:
def __init__(self, value):
self.value = value
def __repr__(self):
return str(self.value)
def __deepcopy__(self, memo):
# do not rly deep copy plx
return self
class1 = MyClass(1)
class2 = MyClass(2)
class3 = MyClass(3)
dict_class = { class1 : {class2, class3}, class2 : {class3}, class3 : {class1}}
#### Want to create a copy of the dictionary with exact same objects... ####
dict_class_copy = deepcopy(dict_class)
print(dict_class)
print(dict_class_copy)
print(class1 in dict_class and class2 in dict_class and class3 in dict_class)
print(class1 in dict_class_copy and class2 in dict_class_copy and class3 in dict_class_copy)
dict_class.pop(class2)
dict_class[class1].remove(class3)
# don't want to change original dictionary key values
print(class2 not in dict_class and class2 in dict_class_copy)
# this breaks w/o deepcopy!
print(class3 not in dict_class[class1] and class3 in dict_class_copy[class1])
# reassign it back
dict_class = dict_class_copy
# i want this back!
print(class2 in dict_class)
print(class3 in dict_class[class1])
Upvotes: 1
Views: 934
Reputation: 4418
Make a "1 level deep" copy of the dict by copying the keys and making copies of the sets. Replace this:
dict_class_copy = deepcopy(dict_class)
with this:
dict_class_copy = {k:set(v) for k,v in dict_class.items()}
and your tests pass.
Upvotes: 1