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
)
我需要多个对象,每个对象都有一个单独的数组。我写了这段代码:
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
)