Что такое duck typing (утиная типизация)?

«Что такое duck typing (утиная типизация)?» — вопрос из категории Python, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Duck typing (утиная типизация) — это концепция в динамически типизированных языках программирования, где тип или класс объекта определяется не его явным объявлением, а набором методов и свойств, которые он имеет. Если объект реализует все необходимые методы, он может быть использован в соответствующем контексте, независимо от его фактического класса.

Принцип: "Если что-то ходит как утка и крякает как утка, то это можно считать уткой".

Пример в Python:

class Duck:
    def quack(self):
        return "Quack!"

class Person:
    def quack(self):  # У Person тоже есть метод quack
        return "Я притворяюсь уткой!"

class Car:
    def honk(self):
        return "Beep!"

def make_it_quack(thing):
    # Функция ожидает, что у объекта есть метод .quack()
    print(thing.quack())

# Работает, т.к. и Duck, и Person имеют .quack()
make_it_quack(Duck())   # Вывод: Quack!
make_it_quack(Person()) # Вывод: Я притворяюсь уткой!

# Вызовет AttributeError во время выполнения (Runtime)
# make_it_quack(Car())  # У Car нет метода .quack()

Связь с тестированием (QA):

  • Моки и стабы: Duck typing активно используется при создании тестовых дублёров (mocks, stubs). Вместо наследования от реального класса можно создать простой объект с нужными методами.

    # Stub для тестирования
    class FakeDatabase:
        def get_user(self, user_id):
            return {'id': user_id, 'name': 'Test User'}  # Предопределённый ответ
    
    # Система под тестом будет работать с FakeDatabase,
    # т.к. у него есть ожидаемый метод .get_user()
  • Протоколы (PEP 544): В современном Python для явного описания "утиного" интерфейса используются typing.Protocol, что улучшает читаемость и поддержку статических анализаторов типов (mypy).
  • Выявление ошибок: Поскольку проверка соответствия интерфейсу происходит во время выполнения, важную роль играет полноценное тестирование, покрывающее различные сценарии использования объектов.