и посмотреть медиа
Code on a Napkin - Python coding
и посмотреть медиа
Channel about programming in Python and other languages. Simple explanations and codes.
Channel about programming in Python and other languages. Simple explanations and codes.
AI bot for text-to-speech and voice cloning in Telegram. Create audio using neural network quickly and easily.
Resource for those interested in programming. Focus on Python, but covers other topics as well. Simple examples and breakdowns.
Знаете ли вы, что __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 Кусочки кода
Открыть канал и посмотреть медиаOnly registered users can share their opinion.
Be the first to share your impression of this resource!