In the example code below, i have a piece of code from a project. I have a self.test_json.test_id, which is an instance of a class being assigned by a json in the constructor, and in the function do_somthing(self) i want to assign a new variable var in the function scope to be equal to the self.test_json.test_id variable, without changing it.
but when i call to do_somthing(self), when i change the value of var the value of self.test_json.test_id changes aswell. why this is happening? as far as i know there is no pointers and references in python, shouldn’t the var create a copy of self.test_json.test_id ?
from types import SimpleNamespace
import json
class Test:
def __init__(self, json_data):
self.tests = json_data.tests
self.test_json = ""
def do_something(self):
for test in self.tests:
var = test.test_json
self.test_json = var
print("The self.test_json is: " + str(self.test_json.test_id))
print("test_json is: " + str(var.test_id))
var.test_id = 6
print("(should be 5, unchanged) The self.test_json is: " + str(self.test_json.test_id))
print("(should be 6, changed) test_json is: " + str(var.test_id))
if __name__ == '__main__':
json_data = b'{"tests": [{"test_json": {"test_id":5 }}]}'
data_as_simple_namespace = json.loads(json_data, object_hook=lambda d: SimpleNamespace(**d))
t = Test(data_as_simple_namespace)
t.do_something()
after the function is called, it will print:
The self.test_json is: 5
test_json is: 5
(should be 5, unchanged) The self.test_json is: 6
(should be 6, changed) test_json is: 6
>Solution :
The self.test_json = var makes the self.test_json a reference to var, they are connected/referring to the same value/memory.
A quick fix could look this:
import copy # HERE
import json
from types import SimpleNamespace
class Test:
def __init__(self, json_data):
self.tests = json_data.tests
self.test_json = ""
def do_something(self):
for test in self.tests:
var = test.test_json
self.test_json = copy.copy(var) # and HERE
print("The self.test_json is: " + str(self.test_json.test_id))
print("test_json is: " + str(var.test_id))
var.test_id = 6
print(
"(should be 5, unchanged) The self.test_json is: "
+ str(self.test_json.test_id)
)
print("(should be 6, changed) test_json is: " + str(var.test_id))
if __name__ == "__main__":
json_data = b'{"tests": [{"test_json": {"test_id":5 }}]}'
data_as_simple_namespace = json.loads(
json_data, object_hook=lambda d: SimpleNamespace(**d)
)
t = Test(data_as_simple_namespace)
t.do_something()