Встречается на 26% собеседований по Python

Что такое полиморфизм

Полиморфизм — это способность функции или метода обрабатывать данные разных типов, а также возможность схожих типов данных, связанных иерархией наследования, иметь различные реализации. В программировании выделяют три основные формы полиморфизма: специальный (ad-hoc), параметрический и полиморфизм подтипов. Чаще всего под полиморфизмом подразумевают именно полиморфизм подтипов, который достигается через наследование и переопределение методов.

Формы полиморфизма

  • Специальный (ad-hoc) полиморфизм — позволяет одной и той же функции обрабатывать разные типы, но с разной реализацией. В языках вроде Java или C++ это реализуется через перегрузку методов (method overloading). В Python перегрузки нет, но её частично имитируют с помощью @singledispatch или проверок типа внутри функции.
  • Параметрический полиморфизм — функция или тип работают с любым типом данных, не меняя своей реализации. В статически типизированных языках это дженерики (например, List<T> в Java). В Python параметрический полиморфизм проявляется естественно из-за динамической типизации: функция может принимать аргументы любого типа, если она не использует специфичные для типа операции.
  • Полиморфизм подтипов — основан на наследовании: класс-наследник может переопределять методы родителя, и вызов метода через ссылку на родительский тип будет использовать реализацию наследника. Это ключевая концепция ООП, позволяющая писать код, работающий с абстракциями, а не с конкретными классами.

Пример на Python

В Python полиморфизм подтипов реализуется через наследование и переопределение методов:

python
class Animal:
    def speak(self):
        raise NotImplementedError

class Dog(Animal):
    def speak(self):
        return "Woof"

class Cat(Animal):
    def speak(self):
        return "Meow"

# Функция принимает любой объект Animal
# и вызывает его метод speak — это и есть полиморфизм
def make_sound(animal: Animal):
    print(animal.speak())

make_sound(Dog())  # Woof
make_sound(Cat())  # Meow

Здесь make_sound не знает, какой именно подтип Animal ей передадут, но благодаря полиморфизму вызов speak() сработает корректно для любого наследника.

Подводные камни и особенности

  • В Python нет строгой типизации, поэтому полиморфизм подтипов работает на основе «утиной типизации»: если объект имеет нужный метод, он может быть использован, даже если не наследуется от ожидаемого класса. Это даёт гибкость, но может приводить к ошибкам, если метод вызывается с объектом, не имеющим нужной реализации.
  • Перегрузка методов в Python отсутствует, но можно использовать functools.singledispatch для создания функций с разным поведением в зависимости от типа первого аргумента.
  • Параметрический полиморфизм в Python не требует явных дженериков, но с появлением type hints (например, List[int]) можно частично имитировать статическую типизацию, хотя это не влияет на выполнение.

Коротко

  • Полиморфизм — способность обрабатывать разные типы данных единообразно.
  • Три формы: специальный (перегрузка), параметрический (дженерики), подтипов (наследование).
  • В Python чаще всего используется полиморфизм подтипов через переопределение методов.
  • Утиная типизация делает полиморфизм в Python более гибким, но требует осторожности.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы