Дескриптор Python без get: журнал присваиваний в set
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Дескрипторы Python: задачи на get, set и set_name.
Односторонний журнал статусов
Модуль мониторинга безопасности принимает сообщения о состоянии защищённого хранилища через простое присваивание в атрибут status. За этим атрибутом стоит необычный data-дескриптор: он определяет метод __set__, но в нём намеренно отсутствует __get__. Каждая корректная непустая строка сразу отправляется в закрытый список истории конкретного экземпляра хранилища. Если же передать пустую строку или значение неподходящего типа, операция немедленно завершается ошибкой ValueError, а уже накопленный список записей остаётся нетронутым.
Поскольку у дескриптора нет собственного метода чтения, стандартный протокол Python ведёт себя особым образом. При обычной попытке прочесть status через точку интерпретатор заглядывает в словарь экземпляра: пока ключа 'status' там нет, чтение возвращает сам объект-дескриптор, закреплённый за классом. Если же записать значение с ключом 'status' напрямую в словарь экземпляра, то последующее чтение вернёт именно его.
Реализуйте этот односторонний механизм валидации и выясните, как именно меняется результат обращения к атрибуту status до и после прямой записи в словарь экземпляра.
Что уже дано
В редакторе представлена заготовка класса StatusHistory с нереализованным методом __set__(self, instance, value).
Вспомогательная функция observe_set_only_history уже доступна в окружении выполнения для тестирования сценариев и не требует самостоятельной реализации.
Что нужно сделать
Реализуйте класс StatusHistory со следующими требованиями:
- Класс определяет метод
__set__(self, instance, value)и намеренно не определяет и не наследует метод__get__. - Дескриптор принимает в качестве
valueтолько непустые строки (включая строки из подклассовstrи строки, состоящие только из пробельных символов). Длина сообщений — от 0 до 1000 символов. - Любые некорректные значения (пустая строка
"", а также значения любых типов, не принадлежащих семействуstr) вызывают исключение семействаValueError. - При возникновении ошибки список истории экземпляра не должен изменяться, а если валидных записей для этого объекта ещё не было — атрибут истории не должен создаваться преждевременно.
- Каждое принятое сообщение добавляется в конец списка истории конкретного экземпляра
instanceпо закрытому имени_status_history. Сам список_status_historyсоздаётся только при первом успешном присваивании валидного значения. - Метод
__set__ни при каких условиях не должен создавать, изменять или удалять ключ'status'в словареinstance.__dict__. - Истории различных экземпляров (включая объекты подклассов владельца) изолированы друг от друга: дескриптор не ведёт общего межэкземплярного состояния.
- Количество операций присваивания и чтения в тестовых сценариях составляет от 0 до 1000.
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля класс верхнего уровня StatusHistory и вызывает его с проверочными аргументами.
Пример использования
class Storage:
status = StatusHistory()
item = Storage()
print(item.status is Storage.status)
item.status = 'ready'
item.__dict__['status'] = 'shadow'
item.status = 'safe'
print(item.status, item._status_history)
Вывод:
True
shadow ['ready', 'safe']
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Дескриптор и dict в Python: кто имеет приоритет при чтении
- Дескрипторы Python: почему значение разделяется между экземплярами
- Дескрипторы Python: валидация и сброс кэша зависимых свойств
- Дескрипторы Python: значения по умолчанию и удаление переопределений
- Дескриптор Python: однократная запись и setname
- Дескриптор Python: проверка связанных полей low и high
