Python: универсальные получатели и сеттеры

TL; DR: необходимо определить уникальный набор геттеров и сеттеров для каждого свойства () 'd переменной. Могу ли я определить общие геттеры и сеттеры и использовать их с любой переменной, которую я хочу?

Предположим, я создаю класс с хорошими геттерами и сеттерами:

class Foo def getter(self): return _bar+' sasquatch' def setter(self, value): _bar = value+' unicorns' bar = property(getter, setter) 

Довольно здорово, правда?

Теперь предположим, что я добавил другую переменную под названием «baz», и я не хочу, чтобы ее не оставляли без внимания это удовольствие от sasquatch / unicorn. Ну, я думаю, я мог бы сделать еще один набор геттеров и сеттеров:

 class Foo def bar_getter(self): return _bar+' sasquatch' def bar_setter(self, value): _bar = value+' unicorns' bar = property(bar_getter, bar_setter) def baz_getter(self): return _baz+' sasquatch' def baz_setter(self, value): _baz = value+' unicorns' baz = property(baz_getter, baz_setter) 

Но это не очень СУХОЙ и бесполезно загромождает мой код. Думаю, я мог бы сделать это немного DRYer:

 class Foo def unicornify(self, value): return value+' unicorns' def sasquatchify(self, value): return value+' sasquatch' def bar_getter(self): return self.sasquatchify(_bar) def bar_setter(self, value): _bar = self.unicornify(_bar) bar = property(bar_getter, bar_setter) def baz_getter(self): return self.sasquatchify(_baz) def baz_setter(self, value): _baz = self.unicornify(_baz) baz = property(baz_getter, baz_setter) 

Хотя это может сделать мой код DRYer, это не идеально. Если бы я хотел unicornify и sasquatchify еще две переменные, мне пришлось бы добавить еще четыре функции!

Должен быть лучший способ сделать это. Могу ли я использовать один общий приемник и / или сеттер для нескольких переменных?

Unicorn-less и безсмысленная реализация реального мира: я использую ORM SQLAlchemy и хочу преобразовать некоторые данные при их хранении и извлечении из базы данных. Некоторые из преобразований применимы к нескольким переменным, и я не хочу загромождать свои классы с помощью геттеров и сеттеров.

5 Solutions collect form web for “Python: универсальные получатели и сеттеры”

Как насчет просто:

 def sasquatchicorn(name): return property(lambda self: getattr(self, name) + ' sasquatch', lambda self, val: setattr(self, name, val + ' unicorns')) class Foo(object): bar = sasquatchicorn('_bar') baz = sasquatchicorn('_baz') 

Несколько более общий:

 def sasquatchify(val): return val + ' sasquatch' def unicornify(val): return val + ' unicorns' def getset(name, getting, setting): return property(lambda self: getting(getattr(self, name)), lambda self, val: setattr(self, name, setting(val))) class Foo(object): bar = getset('_bar', sasquatchify, unicornify) baz = getset('_baz', sasquatchify, unicornify) 

Или, с едва большей работой, вы можете использовать полный протокол дескриптора, как описано в ответе agf .

Для этого используется property протокола дескриптора :

 class Sasicorn(object): def __init__(self, attr): self.attr = "_" + attr def __get__(self, obj, objtype): return getattr(obj, self.attr) + ' sasquatch' def __set__(self, obj, value): setattr(obj, self.attr, value + ' unicorns') class Foo(object): def __init__(self, value = "bar"): self.bar = value self.baz = "baz" bar = Sasicorn('bar') baz = Sasicorn('baz') foo = Foo() foo2 = Foo('other') print foo.bar # prints bar unicorns sasquatch print foo.baz # prints baz unicorns sasquatch print foo2.bar # prints other unicorns sasquatch 

Хотя property фабричной функции может быть хорошо для вашего примера с игрушкой, это звучит, как будто вам нужно больше контроля для вашего реального использования.

Один из моих коллег предложил использовать закрытие, чтобы возвращать функции getter и setter, и это то, что я решил использовать.

 class Foo(object): def setter(var): def set(self, value): setattr(self, var, value+' unicorn') return set def getter(var): def get(self): return getattr(self, var)+' sasquatch' return get bar = property(getter('_bar'), setter('_bar')) f = Foo() f.foo = 'hi' print f.foo 

Но спасибо всем за ваши ответы 🙂

Используя getattribute и setattr, вы можете определить это для всех атрибутов прошлого и будущего.

 class Foo(object): x = 3 def __getattribute__(self, attr): return str(object.__getattribute__(self, attr)) + ' sasquatch' def __setattr__(self, attr, value): object.__setattr__(self, attr, str(value) + ' unicorn') print Foo.x f = Foo() print fx fy = 4 print fy 

Это печатает:

 3 3 sasquatch 4 unicorn sasquatch 
 # coding=utf-8 __author__ = 'Ahmed Şeref GÜNEYSU' class Student(object): def __init__(self, **kwargs): for k, v in kwargs.iteritems(): self.__setattr__(k, v) if __name__ == '__main__': o = Student(first_name='Ahmed Şeref', last_name='GÜNEYSU') print "{0} {1}".format(o.first_name, o.last_name) print o.email 

дает

 Ahmed Şeref GÜNEYSU File "/Users/ahmed/PycharmProjects/sanbox/abstract_classes/object_initializer/__init__.py", line 13, in <module> print o.email AttributeError: 'Student' object has no attribute 'email' Process finished with exit code 137 
  • Python: об улавливании любого исключения
  • Вызывать Python SimpleHTTPServer из командной строки без опции кеша
  • Генератор Python - что не использовать его для
  • Использование GPU, несмотря на настройку CPU_Only, приводит к неожиданному аргументу ключевого слова
  • Назначение функции переменной
  • Можно ли добавлять заголовки в электронные письма, отправляемые приложением?
  • python .rstrip удаляет один дополнительный символ
  • Используйте uuid.uuid4 () для создания нового файла
  •  
    Interesting Posts for Van-Lav

    Ошибка Pyodbc Имя источника данных не найдено, а драйвер по умолчанию не указан парадокс

    Все возможные варианты zip в Python

    Jython конвертирует изображение в оттенки серого, а затем отменяет его

    Попытка поиска первого восходящего прогона в списке Python

    Как мне получить pip для установки определенной версии meld?

    Как я могу выполнить загрузку файлов в twisted.web, которые не сосут?

    использовать scikit-learn для классификации по нескольким категориям

    Как zip (* * n) работает в Python?

    перекодированные команды локальной оболочки с конвейером

    Разность между ненулевым (a), где (a) и argwhere (a). Когда использовать какой?

    Beautifulsoup потерял узлы

    usr / bin / env: плохой интерпретатор Разрешение отклонено -> как изменить fstab

    Есть ли аналог Java IllegalStateException в Python?

    Полоса пробела из вывода шаблона Мако (Pylons)

    Кодек Python ASCII не может кодировать ошибку символа во время записи в CSV

    Python - лучший язык программирования в мире.