Итерируемое свойство

У меня есть библиотека (django-piston), которая ожидает некоторые параметры класса как свойства класса. Я хотел бы определить это значение динамически в методе. Поэтому я хотел сделать что-то вроде:

class MyHandler(BaseHandler): @property def fields(self): fields = self.model._meta.fields + self.model._meta.virtual_fields # Do something more with fields return fields 

Но это не удается:

 'property' object is not iterable 

Поэтому я хотел сделать что-то вроде:

 class iterable_property(property): def __iter__(self): # What here? 

Но я застрял здесь. Как я могу получить свойство, которое также можно повторить?

Ваш оригинальный код выглядит нормально (хотя я бы не назвал локальную переменную тем же именем, что и закрывающая функция).

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

Если вам нужен атрибут класса, свойство не будет работать, и вам нужно будет написать собственный дескриптор для свойства класса:

 class ClassProperty(object): def __init__(self, func): self.func = func def __get__(self, inst, cls): return self.func(cls) class A(object): model_fields = ['field1', 'field2', 'field3'] @ClassProperty def fields(cls): return cls.model_fields + ['extra_field'] print A.fields 

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

 class class_property(property): def __get__(self, instance, type): if instance is None: return super(class_property, self).__get__(type, type) return super(class_property, self).__get__(instance, type) 

и он работает сейчас. 😉

Если я правильно понял, в django-piston обработчик может иметь model и fields как атрибуты класса.

Если это так, ваша проблема может быть решена примерно так:

 class MyHandler(BaseHandler): model = Post class __metaclass__(type): @property def fields(cls): fields = cls.model._meta.fields + cls.model._meta.virtual_fields # Do something more with fields return fields 
Interesting Posts