Python: несколько свойств, один сеттер/получатель

Рассмотрим следующие определения классов

class of2010(object):
    def __init__(self):
        self._a = 1
        self._b = 2
        self._c = 3

    def set_a(self,value):
        print('setting a...')
        self._a = value
    def set_b(self,value):
        print('setting b...')
        self._b = value
    def set_c(self,value):
        print('setting c...')
        self._c = value
    a = property(fset=self.set_a)
    b = property(fset=self.set_b)
    c = property(fset=self.set_c)

Обратите внимание, что set_[a|b|c]() делает то же самое. есть ли способ определить:

def set_magic(self,value):
    print('setting <???>...')
    self._??? = value

один раз и используйте его для a, b, c следующим образом

a = property(fset=self.set_magic)
b = property(fset=self.set_magic)
c = property(fset=self.set_magic)

Ответ 1

def attrsetter(attr):
  def set_any(self, value):
    setattr(self, attr, value)
  return set_any

a = property(fset=attrsetter('_a'))
b = property(fset=attrsetter('_b'))
c = property(fset=attrsetter('_c'))

Ответ 2

Я вижу, что ваши сеттеры просто регистрируют сообщение, а затем просто присваивают значение - на самом деле ваш принятый ответ просто присваивает значение. Используете ли вы этот шаблон, потому что это принятая практика/обычная мудрость на каком-то другом языке, возможно, имя, начинающееся с буквы "J"? Если да, то, пожалуйста, узнайте, что подход Pythonic к этому же дизайну намного проще:

class Of2010(object):
    def __init__(self):
        self.a = 1
        self.b = 2
        self.c = 3

Нет никаких настроек, никаких промежуточных вызовов функций просто для назначения значения. "Что ты говоришь?" Публичное воздействие переменных-членов?!!" Ну, да, на самом деле.

Посмотрите на эти классы с точки зрения клиентского кода. Чтобы использовать свой класс, клиенты создают объект, а затем присваивают свойство "a" , используя:

obj = Of2010()
obj.a = 42

Примечательно, что это тот же самый код для 5-линейного класса I, опубликованного выше.

Почему J-язык поощряет более верный стиль собственности? Сохранение интерфейса класса в случае будущих изменений требований. Если в какой-то момент времени некоторое другое значение объекта должно измениться вместе с любыми изменениями в a, тогда вы должны реализовать механизм свойств. К сожалению, J-язык раскрывает характер механизма доступа атрибутов к клиентскому коду, так что введение свойства в какой-то момент в будущем представляет собой навязчивую задачу рефакторинга, которая потребует перестройки всех клиентов, которые используют этот класс и его атрибут "a" .

В Python это не так. Доступ к атрибуту "a" объекта определяется во время выполнения в вызывающем. Поскольку прямой доступ и доступ к свойствам "выглядят" одинаково, ваш класс Python сохраняет этот интерфейс, даже если фактический механизм отличается. Важно то, что он идентичен в отношении кода клиента.

Итак, в Java, эта сложность свойств вводится с самого начала этого класса (и фактически, Accepted Practice, из всех классов), вне всякого сомнения, что это может понадобиться в будущем. С Python можно начать с реализации Simplest Thing, которая могла бы работать, т.е. Прямого доступа к простым переменным-членам, оставляя сложный подход на время в будущем, что дополнительный материал действительно необходим и имеет ценность. Поскольку этот день, возможно, никогда не наступит, это огромный шаг вперед в получении этой первой рабочей версии вашего кода в дверь.

Ответ 3

class...
 def __setattr__(self, name, value):
  print 'setting', name
  self.__dict__[name] = value

Что это.

Ответ 4

Возможно, вы ищете __setattr__(self, name, value)

Посмотрите здесь