#python #python-3.x
#python #python-3.x
Вопрос:
У меня есть функция со следующей подписью:
def analog_out(device: str, analog_output: str, voltage: (int, float)):
# does some hardware manipulation here, this part is working just fine,
# but i will put a print here just to have something
print(device, analog_output, voltage)
Короче говоря, для этого требуется три параметра.
У меня есть возможность опрашивать подключенное оборудование во время выполнения и определять «имена» analog_output
подключенных устройств. Например, если я опрашиваю конкретное аппаратное обеспечение, я мог бы получить список строк ['ao0', 'ao1']
, каждую из которых было бы уместно поместить в analog_output
функцию.
У меня определен класс, который обеспечит несколько удобный доступ, но я хотел бы сделать его более удобным. На данный момент использование класса удобства выглядит следующим образом:
hw = Hardware()
hw.analog_out(analog_output='ai0', voltage=3.3)
Опять же, все вышесказанное работает просто отлично, но что-то меня беспокоит в интерфейсе. В идеале я хотел бы иметь что-то вроде:
hw.ai0 = 3.3
Я могу опросить аппаратное обеспечение и настроить это в конструкторе Hardware
класса, но, похоже, я не могу определить синтаксис, который работает. Я уверен, что __setattr__
это связано с чем-то или возможно self.__dict__
, но, похоже, я никак не могу сдвинуть дело с мертвой точки. Например, одна из моих осечек, предполагающая, что я пытаюсь записать в ao0
:
self.__dict__['ao0'] = lambda v, d=device: analog_out(d, 'ao0', v)
что позволяет мне делать что-то вроде:
hw.ao0(3.3)
но это не совсем то, что я ищу.
Ответ №1:
Это действительно пример использования для __setattr__
.
class Hardware:
def __setattr__(self, attr, value):
self.__dict__[attr] = value
hw = Hardware()
hw.ai0 = 3.3
Это, вероятно, слишком общее, так как позволяет генерировать выходные данные «на лету». Вы можете исправить это, сверившись attr
с разрешенным списком.
class Hardware:
def __init__(self, allowed_outputs):
self.outputs = allowed_outputs
def __setattr__(self, attr, value):
if attr not in self.outputs:
raise ValueError(f'Non-existent output {attr}')
self.__dict__[attr] = value
hw = Hardware(["ao0", "ao1"])
Комментарии:
1. Вы могли бы добавить
if hasattr(self, key): settatr(self, key, value)
для защиты атрибутов текущего объекта2. Спасибо за ответ. Кажется, что это правильно, но когда я запускаю его в python 3.7, кажется, что
__setattr__
он запускается перед конструктором, поэтому я получаю сообщение об ошибке, посколькуself.outputs
он еще не существует.3. Хорошо, итак
self.outputs
, я отодвинулся от первой регистрации,__setattr__
и это, похоже, решило проблему. У меня есть другие переменные класса, которые устанавливались доself.outputs
, так что они тоже мешали. Еще раз спасибо вам!