и посмотреть медиа
Код на салфетке - Python кодинг
и посмотреть медиа
Канал о программировании на Python и других языках. Простые объяснения и коды.
Канал о программировании на Python и других языках. Простые объяснения и коды.
AI бот для озвучки текста и клонирования голоса в Telegram. Создавай аудио с помощью нейросети быстро и просто.
Ресурс для интересующихся программированием. Фокус на Python, но охватывает и другие темы. Простые примеры и разборы.
Знаете ли вы, что __getattr__ вызывается не при каждом обращении к атрибуту? Сначала Python ищет атрибут обычным путем – в __dict__ инстанса, в классе, дальше по наследованию, вызывая дескрипторы если они попались. __getattr__ в этом поиске не участвует – он вызывается только тогда, когда поиск ничего не нашел и все идет к AttributeError. class User: role = "admin" def __getattr__(self, name): return f"нет такого атрибута: {name}" u = User() print(u.role) # admin – найден обычным поиском, __getattr__ молчит print(u.missing) # нет такого атрибута: missing – поиск провалился role лежит в User.__dict__, поиск заканчивается там же – __getattr__ до вызова не доходит. А вот missing не нашелся нигде, и вместо AttributeError Python вызывает __getattr__. Перехватывать вообще все обращения умеет другой метод – __getattribute__. Он вызывается первым, до всякого поиска по __dict__, и поиск делает уже он сам: class Loud: role = "admin" def __getattribute__(self, name): print(f"обращение: {name}") return super().__getattribute__(name) l = Loud() print(l.role) # обращение: role # admin super().__getattribute__(name) и есть тот самый штатный поиск по цепочке. Если его не вызвать, а вернуть что-то свое, объект перестанет отдавать даже собственные атрибуты. Отсюда и главный риск: обращение к self.anything внутри __getattribute__ снова вызовет __getattribute__, и получится бесконечная рекурсия. На __getattr__ строятся прокси-объекты – обертки, которые делают вид, что они и есть обернутый объект: class Proxy: def __init__(self, target): self._target = target def __getattr__(self, name): print(f"проксируется: {name}") return getattr(self._target, name) class Service: def ping(self): return "pong" p = Proxy(Service()) print(p.ping()) # проксируется: ping # pong print(p._target) # ping в Proxy не определен, поиск проваливается, срабатывает __getattr__ – и обращение уходит на Service. При этом _target лежит в __dict__ инстанса, ищется обычным поиском, и __getattr__ для него не будет вызван. Поэтому рекурсии нет: прокси на __getattr__ пишется без ухищрений, чего не скажешь про __getattribute__. __getattribute__ перехватывает каждое обращение, __getattr__ – только промахи. Для оберток и ленивой подгрузки почти всегда нужен второй. Код на салфетке x Кусочки кода
Открыть канал и посмотреть медиаТолько зарегистрированные пользователи могут делиться своим мнением.
Станьте первым, кто поделится своим впечатлением об этом ресурсе!