Страницы

Поиск по вопросам

понедельник, 23 декабря 2019 г.

Существуют ли генераторы (фабрики) функций?

#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())

Комментариев нет:

Отправить комментарий