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

Python: Define array as instance class attribute

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

    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)

这就是我定义 class 的方式:

    class TempObjectForReadValues():
        read_elements = [None] * 10

结果是:

[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]

也就是说数据覆盖了之前的数据。此外,如果我没有为新对象中的数组分配任何内容,它会保留前一个对象的结果。 :(

我该如何解决?

Python 语法与 Java 和 C++ 不同,它不在 class 主体上指定实例属性。相反,class 正文中指定的任何属性都是 class 属性。 这意味着您的 read_elements 数组本质上是一个在 TempObjectForReadValues class.

的所有实例之间共享的单例

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

class TempObjectForReadValues:
    def __init__(self):
        self.read_elements = [None] * 10

现在,请注意,对于更复杂的 class 层次结构和特定需求,Python 确实实现了一种称为 "descriptor protocol" 的机制,该机制允许指定为 class 属性的专门对象管理 reading/writting 和删除每个实例上具有相同名称的属性。

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

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

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

(这是将代码保持在一行中的 hackish 实现,相当于:

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

)