在 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 引用另一个对象,这是原始对象的副本