Python:将数组定义为实例类属性

Ahm*_*mad 6 arrays attributes class overwrite python-3.x

我需要有几个对象,每个对象都有一个单独的数组。我写了这段代码:

    read_values = list()
    for read_unit in read_units:
        read_value = ReadValues.objects.all().filter(ReadID=read_unit.ReadID)

        element = TempObjectForReadValues()
        for read_element in read_value:
            element.read_elements[read_element.Code] = read_element.ReadValue
        read_values.append(element)
        print(element.read_elements)

    print('  ')
    for test_element in read_values:
        print(test_element.read_elements)
Run Code Online (Sandbox Code Playgroud)

这就是我定义该类的方式:

    class TempObjectForReadValues():
        read_elements = [None] * 10
Run Code Online (Sandbox Code Playgroud)

结果是:

[None, None, 16.0, None, 189.0, 345.0, None, None, None, None]
[None, None, 16.0, 43.0, 876.0, 345.0, None, None, None, None]

[None, None, 16.0, 43.0, 876.0, 345.0, None, None, None, None]
[None, None, 16.0, 43.0, 876.0, 345.0, None, None, None, None]
Run Code Online (Sandbox Code Playgroud)

这意味着数据将被覆盖以前的数据。另外,如果我不向新对象中的数组分配任何内容,它会保存前一个对象的结果。:(

我该如何修复它?

jsb*_*eno 4

与 Java 和 C++ 不同,Python 语法不在类主体上指定实例属性。相反,类主体中指定的任何属性都是 属性。这意味着您的read_elements 数组本质上是在类的所有实例之间共享的单例TempObjectForReadValues

要解决这个问题,只需在对象的初始化代码(即方法)中创建任何旨在作为实例属性的属性__init__

class TempObjectForReadValues:
    def __init__(self):
        self.read_elements = [None] * 10
Run Code Online (Sandbox Code Playgroud)

现在,请注意,对于更复杂的类层次结构和特定需求,Python 确实实现了一种称为“描述符协议”的机制,该机制允许指定为类属性的专用对象来管理每个实例上具有相同名称的属性的读/写和删除。

最常见的用途之一是property(甚至是语言中的内置函数)——它只需要 1 到 3 个可调用参数,每个参数都是属性的 getter/setter/deleter。这种机制还可以用于 ORM 策略、接口实现和很多其他事情。

对于你的情况,你可以这样做:

class TempObjectForReadValues:
    read_elements = property(lambda self: self.__dict__.setdefault("_read_elements", [None] * 10))
Run Code Online (Sandbox Code Playgroud)

(这是一个将代码保持在一行的黑客实现,相当于:

class TempObjectForReadValues:
    @property
    def read_elements(self):
        if not hasattr(self, "_read_elements"):
            self._read_elements = [None] * 10
        return self._read_elements
Run Code Online (Sandbox Code Playgroud)