← Назад к вопросам

В чем разница между интерфейсом на основе абстрактного класса и на основе Protocol в Python?

2.3 Middle🔥 81 комментариев
#Python Core#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Абстрактные классы vs Protocol: два подхода к контрактам

Оба способа определяют контракты для классов, но работают принципиально по-разному. Protocol — это более гибкий и современный подход.

ABC (Abstract Base Classes): явное наследование

ABC — это класс, который определяет интерфейс через абстрактные методы. Классы-наследники должны наследоваться от ABC и реализовать все методы.

Характеристики:

  • Явное наследование — класс должен наследоваться
  • Проверка в runtime — ошибка при создании экземпляра, если не реализованы методы
  • Существует с Python 2.6
  • Строгий контракт — полное совпадение сигнатур
  • Наследование есть — экземпляр является экземпляром ABC
from abc import ABC, abstractmethod

class Animal(ABC):
    """Абстрактный класс"""
    
    @abstractmethod
    def speak(self):
        """Каждое животное должно издавать звук"""
        pass
    
    @abstractmethod
    def move(self):
        pass

class GoodDog(Animal):
    def speak(self):
        return "Woof!"
    
    def move(self):
        return "Running"

dog = GoodDog()
print(isinstance(dog, Animal))  # True

Protocol: структурная типизация

Protocol — это тип, который проверяет, имеет ли объект необходимые методы и атрибуты, независимо от наследования.

Характеристики:

  • Неявное соответствие — не требует наследования
  • Проверка в compile-time — mypy проверяет типы статически
  • Существует с Python 3.8
  • Структурная типизация — проверяется структура, не наследование
  • Утиная типизация — независимо от иерархии
from typing import Protocol

class Animal(Protocol):
    """Протокол для животных"""
    
    def speak(self) -> str:
        ...
    
    def move(self) -> str:
        ...

class Dog:
    def speak(self) -> str:
        return "Woof!"
    
    def move(self) -> str:
        return "Running"

dog = Dog()
process_animal(dog)  # OK для mypy!

Сравнение в таблице

КритерийABCProtocol
НаследованиеОбязательноНЕ требуется
ПроверкаRuntimeCompile-time (mypy)
isinstance()TrueFalse
ГибкостьЖесткаяГибкая
Python 3.5ДаНет
Python 3.8+ДаДа

Практический пример: интеграция сторонних библиотек

from typing import Protocol

class ServiceInterface(Protocol):
    def execute(self) -> str:
        ...

class ExternalService:
    def execute(self) -> str:
        return "result"

def run_service(service: ServiceInterface) -> None:
    print(service.execute())

run_service(ExternalService())  # OK для mypy!

Когда использовать что

ABC лучше для:

  • Вашего собственного кода
  • Гарантии runtime
  • Явных контрактов
  • Python < 3.8

Protocol лучше для:

  • Интеграции сторонних кодов
  • Гибкости и структурной типизации
  • Современного кода (Python 3.8+)
  • Утиной типизации

Заключение

ABC требует явного наследования и проверяется в runtime. Protocol работает со структурной типизацией и проверяется статически mypy. В современном Python (3.8+) Protocol часто предпочтительнее для интеграции с внешним кодом, а ABC — для контроля над вашей иерархией классов.