MXStat
MXStat
Введите текст для поиска
Расширенный поиск каналов
  • Вход на сайт
  • Каталог
    Каталог каналов Региональные подборки Поиск каналов
    Добавить канал
  • Рейтинги
    Рейтинг каналов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Max
Python Разработка | Web Backend, Парсинг & Telegram Bots. Пайтон программирование с нуля. Django, FastAPI и SQL. Уроки для начинающих и IT карьера. Coding.

15 Sep, 10:05

Открыть в Max Поделиться

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

👉 @BookPython

991 14
Каталог
Каталог каналов Подборки каналов Поиск каналов Добавить канал
Рейтинги
Рейтинг каналов Max
Контакты
Написать в Max Написать в Telegram Написать на почту
Всякая всячина
Пользовательское соглашение Политика конфиденциальности
Наши каналы
MXStat в Telegram MXStat в Max
Наши боты
MXAuthBot MXAnalyticsBot
Made by TGStat