Поведение __getattr__ в простом классе
@python_quizРазберем этот квиз
Условие — код, который нужно проанализировать:

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

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

Практические замечания и рекомендации
- Определять
__getattr__через lambda допустимо, но менее читаемо. Предпочтительнее использовать обычное определение метода:

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