TGViewer
Библиотека Python разработчика | Книги по питону Библиотека Python разработчика | Книги по питону @bookpython · 18.1K subscribers
Post #3987 2.07K
Ранее мы затронули типизацию в фикстурах (косвенно), поэтому сегодня поговорим про:

Protocol vs ABC: Утиная типизация на стероидах (Static Duck Typing)

В классическом ООП (Java, C#) и при использовании abc.ABC в Python мы привыкли к Nominal Subtyping (Именная подтипизация). Чтобы объект считался Bird, он должен явно наследоваться от Bird.
Это создает жесткую связность (coupling): ваша реализация должна знать об интерфейсе и импортировать его.

С приходом typing.Protocol (Python 3.8+) мы получили Structural Subtyping (Структурная подтипизация).

В чем суть?
Если класс имеет метод quack(), то это Утка. Неважно, от чего он наследуется. Это и есть та самая «утиная типизация», но теперь поддерживаемая статическим анализатором (mypy, pyright, IDE).

Сравним код:

❌ Старый путь (ABC):


from abc import ABC, abstractmethod

# 1. Жестко определяем интерфейс
class SenderABC(ABC):
@abstractmethod
def send(self, msg: str) -> None: pass

# 2. Обязаны наследоваться!
class EmailService(SenderABC):
def send(self, msg: str) -> None:
print(f"Email: {msg}")

def alert(sender: SenderABC):
sender.send("Alert!")



✅ Новый путь (Protocol):


from typing import Protocol

# 1. Описываем, "что мы ждем от объекта"
class SenderProto(Protocol):
def send(self, msg: str) -> None: ...

# 2. Реализация НИЧЕГО не знает про Protocol
# Никаких импортов и наследования!
class SmsService:
def send(self, msg: str) -> None:
print(f"SMS: {msg}")

# Mypy счастлив: SmsService имеет нужную структуру (метод send)
def alert(sender: SenderProto):
sender.send("Alert!")

alert(SmsService())



Киллер-фича: Retroactive Abstraction (Ретроактивная абстракция)
Представьте, что вы используете стороннюю библиотеку (например, boto3 или клиент Redis). Вы не можете заставить их классы наследоваться от ваших ABC.
С помощью Protocol вы можете создать интерфейс для уже существующего чужого кода, не меняя его, и типизировать свои функции.

Нюансы для Middle+:

1. Runtime: По умолчанию isinstance(obj, MyProtocol) выбросит ошибку. Протоколы - это compile-time фича. Если нужна проверка в рантайме, декорируйте протокол @runtime_checkable.

2. Свойства: В протоколе можно описывать не только методы, но и поля через @property или просто аннотации типов.

Используйте Протоколы, чтобы развязать зависимости между модулями. Это основа принципа Dependency Inversion в Python.

#python #typing #mypy #architecture #clean_code

📲 Мы в MAX

👉@BookPython
  • 👍 6
More from @bookpython
  1. Sep 25, 2026Как быстро очистить список в Python? Сегодня я покажу вам несколько способов очистки списк…
  2. Sep 24, 2026🚀 5 крутых Python-фишек, о которых знают не все Python — мощный и удобный язык, но даже о…
  3. Sep 23, 2026🔥 Как ускорить Python-код в 10 раз? Сегодня покажу вам мощный инструмент для оптимизации…
  4. Sep 21, 202610 полезных библиотек для Python-разработчика Сегодня я подготовил для вас подборку из 10…
  5. Sep 16, 2026Если у вас есть ресурсоемкая задача для процессора и вы хотите использовать все доступные…
  6. Sep 15, 2026Protocol vs ABC: Утиная типизация на стероидах (Static Duck Typing) В классическом ООП (Ja…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →