Python: почему оператор + перегружается, а методы, нет
Статья разбирает два разных значения слова «перегрузка» в Python. В классе нельзя оставить две реализации метода с одним именем: если определить distance() дважды, вторая версия молча заменит первую. Поэтому вызов с аргументами, подходящими только первой версии, завершится ошибкой. В Java, напротив, несколько методов с одним именем могут сосуществовать, а нужный вариант выбирается по числу аргументов; это и есть перегрузка методов.
При этом отсутствие перегрузки методов не мешает Python использовать оператор + и для чисел, и для строк. Это другой механизм, перегрузка операторов. Класс может определить специальный метод add; в примере Point он возвращает новую точку с суммой координат. После этого выражение Point(1, 1) + Point(2, 2) даёт точку с координатами 3 и 3. У float и str также есть свои реализации add, отвечающие соответственно за сложение и конкатенацию строк.
Если всё же нужен метод distance(), принимающий разные формы аргументов, автор предлагает два подхода. Первый, сделать distance() диспетчеризирующим методом: проверять тип первого аргумента через isinstance(), наличие второго аргумента и передавать расчёт отдельным методам для Point, пары координат или двух чисел. Второй, обычно предпочтительный, начать с декоратора @singledispatch из модуля functools, который регистрирует разные обработчики по типу первого аргумента. Однако в приведённом классе Point логика выбора слишком сложна для @singledispatch.
Ключевые факты
- Повторное определение метода с тем же именем в классе Python заменяет предыдущую версию; перегрузки методов по числу аргументов нет.
- Оператор + перегружается через специальный метод add, который можно определить в собственном классе.
- В примере сложение Point(1, 1) и Point(2, 2) возвращает новую точку с координатами 3 и 3.
- Для разных форм вызова одного метода можно вручную выбирать обработчик по типам и наличию аргументов.
- @singledispatch из functools подходит для выбора реализации по типу первого аргумента, но не для всякой сложной логики диспетчеризации.
Почему это важно
Статья разделяет два похожих по названию, но разных механизма: Python не выбирает между несколькими методами с одинаковым именем, зато позволяет задавать поведение операторов для своих объектов.
Кому это важно
Разбор полезен начинающим разработчикам Python, которые ожидают от языка поведения Java и хотят понять, почему + работает по-разному для чисел, строк и собственных классов.
Как это применить
Чтобы поддержать сложение экземпляров класса, определите add. Если один метод должен принимать разные формы аргументов, сделайте явный выбор обработчика по типам и аргументам либо сначала рассмотрите @singledispatch.
Можно ли доверять
Это объяснительный учебный материал с короткими фрагментами кода: показанные примеры прямо иллюстрируют замену повторно определённого метода и использование add.
Риски и подводные камни
Вручную написанный диспетчер может разрастись из-за проверок типов и аргументов. @singledispatch выбирает реализацию только по типу первого аргумента, поэтому не покрывает пример Point с более сложными условиями выбора.
«Можно сказать, что термин «перегруженный»... перегружен.»
— Из статьи