← Назад к вопросам
Используешь ли Protocol из библиотеки typing в Python
1.7 Middle🔥 131 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Protocol в Python: Структурная типизация
Да, я активно использую Protocol из модуля typing. Это инструмент для реализации структурной типизации (duck typing with types) в Python.
Что такое Protocol?
Protocol — это интерфейс, который определяет набор методов и атрибутов, которые должен иметь объект. В отличие от классического наследования, объект не обязательно должен явно наследоваться от Protocol — достаточно иметь нужные методы.
from typing import Protocol
class Drawable(Protocol):
def draw(self) -> None:
...
class Circle:
def draw(self) -> None:
print("Рисую круг")
class Square:
def draw(self) -> None:
print("Рисую квадрат")
def render(obj: Drawable) -> None:
obj.draw()
render(Circle())
render(Square())
Protocol vs ABC vs Inheritance
Protocol (структурная типизация)
from typing import Protocol
class Comparable(Protocol):
def __lt__(self, other: "Comparable") -> bool: ...
def __eq__(self, other: object) -> bool: ...
class Version:
def __init__(self, major: int, minor: int):
self.major = major
self.minor = minor
def __lt__(self, other: "Version") -> bool:
return (self.major, self.minor) < (other.major, other.minor)
def __eq__(self, other: object) -> bool:
if not isinstance(other, Version):
return False
return (self.major, self.minor) == (other.major, other.minor)
def find_min(items: list[Comparable]) -> Comparable:
return min(items)
ABC (абстрактный базовый класс)
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def make_sound(self) -> None:
pass
class Dog(Animal):
def make_sound(self) -> None:
print("Гав")
Реальные примеры использования Protocol
1. Context Manager Protocol
from typing import Protocol
class ContextManager(Protocol):
def __enter__(self) -> "ContextManager":
...
def __exit__(self, exc_type, exc_val, exc_tb) -> bool:
...
class Database(ContextManager):
def __enter__(self):
print("Подключение к БД")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Закрытие БД")
return False
2. Repository Pattern
from typing import Protocol, Generic, TypeVar
T = TypeVar("T")
class Repository(Protocol[T]):
def find_by_id(self, id: int) -> T | None: ...
def save(self, item: T) -> None: ...
def delete(self, id: int) -> None: ...
class User:
def __init__(self, id: int, name: str):
self.id = id
self.name = name
class UserRepository:
def find_by_id(self, id: int) -> User | None:
pass
def save(self, item: User) -> None:
pass
def delete(self, id: int) -> None:
pass
Runtime checkable
from typing import Protocol, runtime_checkable
@runtime_checkable
class Hashable(Protocol):
def __hash__(self) -> int: ...
class MyClass:
def __hash__(self) -> int:
return 42
obj = MyClass()
print(isinstance(obj, Hashable))
Когда использовать Protocol?
- Зависимости — не привязываем код к конкретным классам
- Тестирование — легче создавать mock-объекты
- Расширяемость — новые классы работают с интерфейсом
- Duck typing with types — Python way с типизацией
- Инверсия зависимостей — следуем SOLID принципам