在 python 中,当在 class 中将变量分配给 self 变量时,它是指向 self 变量的指针?
in python, When assigning a variable to self variable in a class its a pointer to the self variable?
在下面的示例代码中,我有一段来自项目的代码。我有一个 self.test_json.test_id
,它是 class 的一个实例,在构造函数中由 json 分配,在函数 do_somthing(self)
中我想分配一个新变量 var
在函数范围内等于 self.test_json.test_id
变量,而不改变它。
但是当我调用 do_somthing(self)
时,当我更改 var
的值时,self.test_json.test_id
的值也会更改。为什么会这样?据我所知 python 中没有指针和引用,var
不应该创建 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()
函数调用后,会打印:
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
self.test_json = var
使 self.test_json
成为对 var
的引用,它们 connected/referring 对相同的 value/memory。
快速修复可能如下所示:
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()
import copy
...
self.test_json = copy.copy(var) # instead of self.test_json = var
解释:
- 您的 var 是对具有字段 'test_id'
的对象的引用
- 您代码中的self.test_json成为对相同对象
的另一个引用
- 使用 copy.copy() 导致 self.test_json 引用另一个对象,这是原始对象的副本
在下面的示例代码中,我有一段来自项目的代码。我有一个 self.test_json.test_id
,它是 class 的一个实例,在构造函数中由 json 分配,在函数 do_somthing(self)
中我想分配一个新变量 var
在函数范围内等于 self.test_json.test_id
变量,而不改变它。
但是当我调用 do_somthing(self)
时,当我更改 var
的值时,self.test_json.test_id
的值也会更改。为什么会这样?据我所知 python 中没有指针和引用,var
不应该创建 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()
函数调用后,会打印:
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
self.test_json = var
使 self.test_json
成为对 var
的引用,它们 connected/referring 对相同的 value/memory。
快速修复可能如下所示:
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()
import copy
...
self.test_json = copy.copy(var) # instead of self.test_json = var
解释:
- 您的 var 是对具有字段 'test_id' 的对象的引用
- 您代码中的self.test_json成为对相同对象 的另一个引用
- 使用 copy.copy() 导致 self.test_json 引用另一个对象,这是原始对象的副本