2015-04-22 2 views
1

Мне нужно иметь несколько объектов, каждый из которых имеет отдельный массив. Я написал этот код:Python: Определить массив как атрибут класса экземпляра

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

Это означает, что данные будут перезаписаны на предыдущих , Кроме того, если я не присваиваю ничего массиву в новом объекте, он содержит результаты предыдущего. :(

Как я могу это исправить?

ответ

1

синтаксиса Python, в отличие от Java и C++, не определяет атрибуты экземпляра на теле класса. Вместо этого, любые атрибуты, заданные в классе теле класса атрибутов. это означает, что ваш read_elements массива, по существу, одноэлементен общие для всех экземпляров вашего TempObjectForReadValues класса

Чтобы исправить это, просто создать все атрибуты предназначены в качестве экземпляра атрибутов внутри кода инициализации для объектов (т.е. метода __init__).:

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

Теперь, обратите внимание, что для более сложных иерархий классов и конкретных потребностей, Python делает реализовать механизм, называемый «дескриптор протоколом», который позволяет специализированные объекты, назначенные как класс атрибуты для управления чтением/сочинительства и удалением атрибутов с одинаковые имена для каждого экземпляра.

Одним из наиболее распространенных видов использования является property (который является даже встроенной функцией на языке) - он требует всего от 1 до 3 вызываемых параметров, каждый из которых является получателем/установщиком/удалением атрибута , Этот механизм можно также использовать для стратегий ORM, реализации интерфейса и многих других вещей.

В вашем случае, вы можете сделать:

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

(это хак реализация, чтобы сохранить код в одной строке, и эквивалентно:

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

)

+0

Большое спасибо за ваш идеальный ответ. – Ahmad

Смежные вопросы