Я ищу элегантный способ замены методов установки / получения, обрабатывающих сложные типы данных, свойствами с помощью декоратора @property.
Класс, над которым я работаю, должен представлять какой-то (сеть)диммер.Можно запросить / отправить «ресурсы», адресованные определенным идентификатором, для управления устройством.Я хотел бы представить эти «ресурсы» как свойства моего класса, скрывающие механизм запроса / отправки и зашифрованные идентификационные номера.Некоторые из этих «ресурсов» являются просто примитивными типами (int, float, ...), но некоторые являются более сложными, поэтому я просто создал для них простые классы.Это прекрасно работает, но есть ужасный источник ошибки: невозможно напрямую изменить атрибут этого свойства, я должен установить свойство полностью каждый раз.
DUMMY_DB = {0x0001: bytearray([0x00])}
class State:
def __init__(self, on, value):
self.on = on
self.value = value
@staticmethod
def from_int(val):
return State(bool(val & 0x80), val & 0x7f)
def __int__(self):
return self.on << 7 | self.value
class Dimmer:
@property
def state(self) -> State:
return State.from_int(self._request(0x0001)[0]) # ID 0x0001 => State
@state.setter
def state(self, val: State):
self._send(0x0001, [int(val)]) # ID 0x0001 => State
# several more properties...
def _request(self, ident) -> bytearray:
# usually get resource 'ident' from network/file/...
return DUMMY_DB[ident]
def _send(self, ident, value):
# usually set resource 'ident' on network/file/... using value
DUMMY_DB[ident] = value
if __name__ == '__main__':
dimmer = Dimmer()
print(dimmer.state.on, dimmer.state.value) # start state
dimmer.state.on = True
dimmer.state.value = 15
print(dimmer.state.on, dimmer.state.value) # state did not change
dimmer.state = State(True, 15)
print(dimmer.state.on, dimmer.state.value) # state changed
Первая печать простопоказать начальное состояние («Ложь 0»).Но вторая печать показывает, что
dimmer.state.on = True
dimmer.state.value = 15
бесполезны.Это потому, что dimmer.state возвращает новый изменяемый объект, который изменяется и уничтожается без дальнейшего использования.Только после полного присваивания свойства вызывается метод установки и вызывается Dimmer._send.
Я думаю, что это может быть чрезвычайно неинтуитивно и подвержено ошибкам.У вас есть предложения по улучшению дизайна?