#python #property #классы
Дано: класс с десятком полей. Необходимо: с помощью встроенного декоратора @property преобразовать каждое поле в свойство т.е. class Static: def __init__(self, **kwargs) if 'today' in kwargs: self.today = kwargs['today'] else: self.today = datetime.date.today() //поля в таком-же стиле т.е. разная статика @property def today(self): return self.today @today.setter def today(self,value): self.today = value @today.deleter def today(self): del self.today и так с каждым полем. В результате очень много дублирующегося кода. Суть вопроса: существует - ли более красивое/питоновское(Пайтоновское) решение или все это оформить в отдельном файле как есть? Возможно, существуют "Генераторы(фабрики) функций(методов)" или декораторы, или неизвестное мне решение? Интересуют идеи, мысли и личный опыт Спасибо ReinRaus - Решение простое и гениальное. O_o и тут я понял как-же мало я знаю Cсылка рано или поздно станет битой, с Вашего разрешения, выложу код здесь Вопрос решен. props={} def myProp(fn): props[fn.__name__]=fn class test(): def __init__(self): self.x=5 def __getattribute__(self, name): if name in props.keys(): return props[name](self) return object.__getattribute__(self, name) def __delattribute__(self, name): if name in props.keys(): del props[name] return object.__delattribute__(self, name) def __setattr__(self, name, value): if name in props.keys(): return props[name](self, value) return object.__setattr__(self, name, value) @myProp def myfunc(self, value=None): if value: self.x=value*2 return self.x-2 x= test() print(x.myfunc) x.myfunc=6 print(x.myfunc)
Ответы
Ответ 1
Языком это не предусмотрено. Можно попробовать сделать свою форму записи. Я реализовал в такой форме: @myProp def propName(self, value=None): if value: ... # это setter return ...# это геттер Реализация здесь: http://ideone.com/Y5HYEn У меня не получилось навести красоту: внести массив props в сам класс, потому что на момент компиляции декораторов класса test не существует, поэтому я вынес этот массив в глобальный. Некроправка Захотел сделать себе так же, но предварительно навел небольшую красоту, теперь просто есть класс, который нужно унаследовать. class test(myProp): @myProp.wrapper def myfunc(self, value=None): if value: # setter return # getter Полный код: http://ideone.com/ZsOF5z class myProp: __props={} def __getattribute__(self, name): if name in object.__getattribute__(self, "_myProp__props").keys(): return self.__props[name](self) return object.__getattribute__(self, name) def __delattribute__(self, name): if name in self.__props.keys(): del self.__props[name] return object.__delattribute__(self, name) def __setattr__(self, name, value): if name in self.__props.keys(): return self.__props[name](self, value) return object.__setattr__(self, name, value) @classmethod def wrapper(self, fn): self.__props[fn.__name__]=fn class test(myProp): def __init__(self): self.x=5 @myProp.wrapper def myfunc(self, value=None): if value: self.x=value*2 return self.x-2Ответ 2
Предложу альтернативу. Property может быть и не декоратором вовсе. UPD Я тут подумал. Мне ведь никто не мешает использовать синтаксис декораторов для оборачивания класса. UPD2 Ну и никто не мешает запихать служебную функцию make_prop поглубже. def set_props(prop_names): def makeprop(container_name): def getter(self): return getattr(self, container_name) def setter(self, value): setattr(self, container_name, value) def deleter(self): delattr(self, container_name) return property(getter, setter, deleter) def wrapper(cl): props = map(lambda x: makeprop('_' + x), prop_names) for prop_name, prop in zip(prop_names, props): setattr(cl, prop_name, prop) return cl return wrapper @set_props(('today',)) class T(object): def __init__(self, **kwargs): self.today = kwargs.get('today', datetime.date.today())
Комментариев нет:
Отправить комментарий