Дескриптор Python: проверка связанных полей low и high
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Дескрипторы Python: задачи на get, set и set_name.
Взаимный инвариант порогов калибровки
В блоке автоматической калибровки рабочий диапазон измерений задаётся двумя числовыми полями: нижней границей low и верхней границей high. Управление обоими порогами поручено одному и тому же data-дескриптору Bound. При настройке дескриптор получает имя парного атрибута и свою роль — указывает, за какую именно границу он отвечает.
Границы могут настраиваться раздельно. При записи целого числа дескриптор обращается к парному порогу того же прибора. Если вторая граница ещё не установлена, новое значение принимается сразу. Но если парное число уже существует, дескриптор следит за строгим порядком: нижняя граница обязана оставаться строго меньше верхней. При любой попытке сделать low больше либо равным high дескриптор возбуждает ValueError, оставляя прежнее состояние прибора нетронутым.
Пока граница не была задана вовсе, прямое обращение к ней завершается ошибкой AttributeError, а чтение атрибута через сам класс возвращает управляющий объект дескриптора. Реализуйте класс Bound, который поддерживает этот взаимный инвариант при независимом обновлении порогов.
Что уже дано
В редакторе представлена заготовка класса Bound со специальными методами __init__, __set_name__, __get__ и __set__, тела которых вам предстоит написать.
Вспомогательная функция observe_ordered_bounds доступна во время проверки в среде исполнения, её реализовывать не нужно.
Что нужно сделать
Реализуйте класс Bound со следующей сигнатурой конструктора: Bound(partner_name, role).
Параметры конструктора:
partner_name— строковое имя парного атрибута-дескриптора в том же классе-владельце;role— строковая роль границы:'low'для нижней границы или'high'для верхней границы. Для каждого поля создаётся собственный экземплярBound, а конкретные имена атрибутов в классе могут отличаться.
Требования к поведению дескриптора:
- Реализуйте data-дескриптор через методы
__get__и__set__. Имя собственного атрибута можно зафиксировать через__set_name__(self, owner, name)при определении класса-владельца. - Доступ через класс (когда аргумент
instance is Noneв__get__) должен возвращать сам объект дескриптора (self). - Доступ через экземпляр
instanceк порогу, который ещё ни разу не был установлен для данного объекта, должен возбуждать исключение из семействаAttributeError. - При установке значения через
__set__(self, instance, value)на вход подаются только корректные целые числа в диапазоне от -1 000 000 до 1 000 000. - Если парная граница
partner_nameдля данногоinstanceещё не задана, присваиваемое значение принимается безоговорочно. - Если парная граница уже установлена, дескриптор обязан проверить строгий инвариант
low < high. Если новое значение нарушает этот порядок (то естьlow >= high), метод должен возбудить исключение из семействаValueError. - Проверка порядка должна происходить строго до того, как текущее сохранённое состояние какого-либо порога будет изменено. При возникновении ошибки прежние значения порогов в объекте остаются нетронутыми.
- Состояния порогов должны храниться независимо для каждого экземпляра класса-владельца и для каждого дескриптора, включая случаи наследования классов.
- Никакой специальной обработки других типов данных, удаления атрибутов, автоматической подгонки (clamping), перестановки мест или принудительной инициализации парной границы реализовывать не требуется.
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля класс верхнего уровня Bound и тестирует его на сериях обновлений.
Пример использования
class Instrument:
low = Bound('high', 'low')
high = Bound('low', 'high')
unit = Instrument()
unit.high = 10
unit.low = 3
try:
unit.low = 10
except ValueError:
print('rejected')
print(unit.low, unit.high)
Вывод:
rejected 3 10
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Дескриптор и dict в Python: кто имеет приоритет при чтении
- Дескрипторы Python: почему значение разделяется между экземплярами
- Дескрипторы Python: валидация и сброс кэша зависимых свойств
- Дескрипторы Python: значения по умолчанию и удаление переопределений
- Дескриптор Python: однократная запись и setname
- Дескриптор Python без get: журнал присваиваний в set
