#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())
Комментариев нет:
Отправить комментарий