2011-10-17 4 views
3

Я хочу группировать атрибуты экземпляров класса, так что было бы легко выполнить итерацию по всем атрибутам, принадлежащим группе. Очевидным ответом было бы включить все это в список или dict, но тогда я не смог бы получить к ним доступ как атрибуты своего объекта, и я бы предпочел это.Элегантный способ группировки атрибутов

В некотором коде должно быть ясно, что я хочу. Здесь у меня есть список и реальные атрибуты.

class Vectors(object): 

    def __init__(self, v1, v2, v3): 
     self.v1 = v1 
     self.v2 = v2 
     self.v3 = v3 
     self.rotatable = ['v2', 'v3'] 

    def rotate(self, angle): 
     for v in self.rotable: 
      new_vector = do_rotate(getattr(self, v), angle) 
      setattr(self, v, new_vector) 

class MoreVectors(Vectors): 
    def __init__(self, v4, *args, **kwargs): 
     super(MoreVectors, self).__init__(*args, **kwargs) 
     self.v4 = v4 
     self.rotable.append('v4') 

Теперь при вызове rotate() он знает, что векторы вращать и я могу добавить больше векторов в этот список динамически. Однако, хотя это и делает свою работу, для меня это выглядит не так элегантно, как я должен сам управлять списком.

Есть ли более простой способ написать это? Я думал о сохранении всех атрибутов в словаре, где каждая группа является ключом, а затем используйте properties(), чтобы я мог получить доступ ко всем элементам словаря в качестве атрибутов. Это было бы достаточно чисто для меня, но я не знаю, как динамически устанавливать свойства внутри метода.

+2

В общем, если у вас есть атрибуты с именем 'v1', 'v2', ...,' vn', возможно, что-то не так с вашим дизайном. Что происходит с доступом к объектам «obj.vectors [0]» и т. Д.? – geoffspear

+1

В этом примере решением является 'def rotate_vectors (angle, * vectors): return [do_rotate (вектор, угол) для вектора в векторах]'. Использование класса глупо. –

+0

Хорошо. Этот класс является просто упрощением моего реального кода. В моем реальном коде у меня есть описательные имена всех моих векторов, и класс более сложный, чем этот. Я просто извлек часть, которая была актуальна. –

ответ

3

Как насчет сделать rotatable атрибутом Vector класса:

class Vector(object): 
    def __init__(self,v,rotatable=False): 
     self.value = v 
     self.rotatable = rotatable 

И затем использовать properties для доступа к значениям легко:

class Vectors(object): 
    def __init__(self, v1, v2, v3): 
     self.vectors = [Vector(v1),Vector(v2,rotatable=True),Vector(v3,rotatable=True)] 
    @property 
    def v1(self): 
     return self.vectors[0].value 
    @property  
    def v2(self): 
     return self.vectors[1].value 
    @property  
    def v3(self): 
     return self.vectors[2].value 
    def rotate(self, angle): 
     for vector in self.vectors: 
      if vector.rotatable: 
       vector.value = do_rotate(vector.value, angle) 

class MoreVectors(Vectors): 
    def __init__(self, v4, *args, **kwargs): 
     super(MoreVectors, self).__init__(*args, **kwargs) 
     self.vectors.append(Vector(v4,rotatable=True)) 
    @property 
    def v4(self): 
     return self.vectors[3].value 
+0

Я полагаю, вы имели в виду 'self.rotatable = rotatable' в конструкторе' Vector'. Кстати, вы можете просто использовать 'namedtuple' для него. – 9000

+0

@ 9000: Спасибо за исправление ('self.rotatable = rotatable'). Я не буду использовать 'namedtuple' здесь, поскольку изменяется значение' vector.value'. Выполнение этого с помощью 'namedtuple' требует вызова частного метода' _replace'. – unutbu

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