Поведение __getattr__ в простом классе

Поведение __getattr__ в простом классе

@python_quiz

Разберем этот квиз

Условие — код, который нужно проанализировать:

python

Коротко: при попытке обратиться к несуществующему атрибуту Python вызовет __getattr__, и в данном примере на экран будет выведено строковое значение, которое возвращает эта функция.

Как это работает (пошагово)

  • При любом обращении к атрибуту сначала вызывается механизм поиска атрибута (включая __getattribute__).
  • Если атрибут не найден обычным способом, Python пытается вызвать метод __getattr__(self, name).
  • В коде выше __getattr__ задан как лямбда-функция с двумя параметрами: self и name, и всегда возвращает строку 'miss'.
  • Следовательно, выражение A().x приведёт к вызову этой лямбды и вернёт 'miss', который затем печатается.

Демонстрация

python

Анализ вариантов ответов

  • "Напечатает 'miss'": соответствует поведению кода — при отсутствии атрибута __getattr__ возвращает 'miss', и это печатается.
  • "Вызовет AttributeError — атрибут отсутствует": нет — __getattr__ срабатывает именно для обработки отсутствующих атрибутов; если он возвращает значение, исключение не поднимается.
  • "Напечатает None": нет — функция явно возвращает строку 'miss', не None.
  • "Сгенерирует TypeError из-за неправильно определённого __getattr__": в данном примере сигнатура метода корректна (self, name), поэтому TypeError не возникает. TypeError мог бы появиться, если бы __getattr__ был определён с неверным количеством аргументов. Пример неверной сигнатуры:
python

Практические замечания и рекомендации

  • Определять __getattr__ через lambda допустимо, но менее читаемо. Предпочтительнее использовать обычное определение метода:
python
  • __getattr__ вызывается только для отсутствующих атрибутов. Если атрибут присутствует в экземпляре или классе, __getattr__ не будет вызван.
  • Если вы хотите перехватывать *все* обращения к атрибутам (и при этом вручную обрабатывать доступ к существующим атрибутам), используйте __getattribute__, но будьте осторожны — легко вызвать рекурсию.
  • При реализации __getattr__ обычно логично при невозможности вернуть значение поднимать AttributeError (а не возвращать None), чтобы поведение оставалось ожидаемым для внешнего кода.

Вывод

В представленном фрагменте при обращении к несуществующему атрибуту вызывается __getattr__, который возвращает строку 'miss', поэтому на экран выводится именно эта строка. Определённая через lambda сигнатура корректна, но для читаемости и отладки лучше использовать обычную функцию.

Report Page