Какие магические методы существуют в Python
Что проверяют
Понимаете ли вы протоколы Python: как len(), for, +, with и квадратные скобки превращаются в вызовы методов класса. Для data и ML следом почти всегда спрашивают, что нужно, чтобы написать свой Dataset в PyTorch.
Как отвечать
Сгруппируйте методы по протоколам:
- создание и представление:
__new__создаёт объект,__init__его настраивает;__repr__для разработчика,__str__для пользователя. Если есть только__repr__,str()использует его; - контейнеры:
__len__,__getitem__,__setitem__,__contains__,__iter__. Map-styleDatasetв PyTorch требует__getitem__и__len__,IterableDatasetстроится на__iter__; - сравнение и хеш:
__eq__,__lt__и остальные. Определили__eq__без__hash__, и объект перестаёт быть хешируемым: вsetи в ключи словаря его уже не положить; - арифметика:
__add__,__mul__,__matmul__(оператор@), отражённые__radd__. Метод, который не умеет работать с типом, возвращаетNotImplemented, и Python пробует метод второго операнда; - вызов:
__call__. В PyTorchmodel(x)идёт черезnn.Module.__call__, который запускает хуки и потомforward, поэтомуforwardнапрямую не зовут; - контекстный менеджер:
__enter__и__exit__, так работают файлы изopen()иtorch.no_grad(); - атрибуты:
__getattr__вызывается только для отсутствующего атрибута,__getattribute__на каждый доступ.
Добавьте пример из pandas: df == 0 вызывает __eq__ и возвращает таблицу булевых значений, а __bool__ у DataFrame бросает ValueError, поэтому if df == 0: падает с ошибкой про неоднозначность.
Где спотыкаются
Называют __init__ конструктором и не знают про __new__. Разница всплывает на неизменяемых типах и синглтонах.
Путают NotImplemented и NotImplementedError. Первое возвращают из операторов, второе бросают из абстрактных методов.
Вызывают методы напрямую, obj.__len__() вместо len(obj), или присваивают их экземпляру. Python ищет специальные методы на типе, поэтому метод, записанный в сам объект, оператор не увидит.