TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • flag Russian
    Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
Библиотека Python разработчика | Книги по питону

15 Sep, 10:04

Открыть в Telegram Поделиться Пожаловаться

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

1.1k 0 14 6
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot