I'm doing something wrong in the code below. I have a method (update_dictonary) that changes a value or values in a dictionary based on what is specificed in a tuple (new_points).
Before I update the dictionary, I want to save that version in a list (history) in order to be able to access previous versions. However, my attempt below updates all dictionaries in history to be like the latest version.
I can't figure out what I'm doing wrong here.
test_dict = {'var0':{'var1':{'cond1':1,
'cond2':2,
'cond3':3}
}
}
class version_control:
def __init__ (self, dictionary):
self.po = dictionary
self.history = list()
self.version = 0
def update_dictionary(self, var0, var1, new_points):
po_ = self.po
self.history.append(po_)
for i in new_points:
self.po[var0][var1][i[0]] = i[1]
self.version = 1
def get_history(self, ver):
return self.history[ver]
a = version_control(test_dict)
new_points = [('cond1', 2),
('cond2', 0)]
a.update_dictionary('var0', 'var1', new_points)
new_points = [('cond3', -99),
('cond2', 1)]
a.update_dictionary('var0', 'var1', new_points)
print(a.get_history(0))
print(a.get_history(1))
CodePudding user response:
Try this
from copy import deepcopy
...
def update_dictionary(self, var0, var1, new_points):
po_ = deepcopy(self.po)
self.history.append(po_)
for i in new_points:
self.po[var0][var1][i[0]] = i[1]
self.version = 1
...
The problem here is that when you assign po_= self.po
you expect po_
to a new variable with a new memory id but actually, you just make a shallow copy(same memory id) of your dictionary. This means if you update the self.po
then op_
will automatically update.
To solve this problem by using deepcopy
from the copy
module(Built-in). It will create a new variable.
You can use this code to save the data into a JSON file.
import json
class version_control:
def __init__(self, dictionary):
self.po = dictionary
self.version = 0
self.ZEROth_version()
def update_dictionary(self, var0, var1, new_points, version=None):
self.version = 1
for i in new_points:
self.po[var0][var1][i[0]] = i[1]
# set the ver to version if given else set to self.version
ver = self.version if version is None else version
with open("version.json", "r") as jsonFile:
# loading the data from the file.
data = json.load(jsonFile)
data[str(ver)] = self.po
with open("version.json", "w") as jsonFile:
# save the updated dictionary in json file
json.dump(data, jsonFile, indent=4)
def get_history(self, ver):
try:
with open("version.json", "r") as jsonFile:
# I don't use .get here. I will catch key errors in except block. I don't want to add an if statement to check for None. But string if you want you can add that.
return json.load(jsonFile)[str(ver)]
# Checking if the file not exists or is empty
except (json.decoder.JSONDecodeError, FileNotFoundError, KeyError) as e:
print("File or Version not found")
def ZEROth_version(self):
with open("version.json", "w") as f:
data = {0: self.po}
json.dump(data, f, indent=4)
I have explained some main points if you want more explanation then comment, I will reply as soon as possible.