Мы уже с вами узнали:
• Утиная типизация — “если выглядит как утка и крякает как утка — это утка”
• Гусиная типизация — “эта утка официально записана в реестре как утка” (через ABC)
Теперь познакомимся с третьим подходом — статической утиной типизацией через Protocol.
Что это такое❓
Protocol из модуля typing позволяет описать интерфейс по ожидаемому поведению — без наследования.
Если у объекта есть нужные методы — он считается совместимым.
from typing import Protocol
class Writer(Protocol):
def write(self, data: str) -> None: ...
class FileWriter:
def write(self, data: str) -> None:
print(f"Пишу: {data}")
def save(w: Writer, msg: str):
w.write(msg)
save(FileWriter(), "Привет!")
Обрати внимание: FileWriter не наследует Writer, но типовые анализаторы (mypy, pyright) поймут — всё ок.
Потому что поведение совпадает.
Зачем это нужно❓
• Статическая проверка интерфейсов до запуска
• Без isinstance() и жёсткой иерархии
• Отлично подходит для тестов, моков
• Совместим с mypy, Pyright, Pylance и другими инструментами
• С полной свободой: хочешь — наследуй, хочешь — просто реализуй нужные методы
Утиная типизация была про “смотрим, что умеет объект”.
Статическая утиная — про “давайте это ещё и проверим заранее”.
✔️ Коротко:
• Protocol — это интерфейс без наследования
• Работает по принципу “если поведение совпадает — значит, подходит”
• Используется для статической проверки типов
• Совместим с mypy, Pyright и другими анализаторами
Можем ли мы проверить, что утка это утка используя протокол в рантайме?
Да например так:
from typing import Protocol, runtime_checkable
@runtime_checkable
class Writer(Protocol):
def write(self, data: str) -> None: ...
class FileWriter:
def write(self, data: str) -> None:
print("Пишу:", data)
fw = FileWriter()
print(isinstance(fw, Writer)) # True
🧠 Статическая утиная типизация помогает писать гибкий, но при этом безопасный код.
Это некий баланс между свободой и контролем.
Более подробно про протоколы можно почитать тут.
——————————-
📱 TG-сообщество
📱 Обучение
📱 Отзывы
