← Назад к вопросам

Используешь ли Generic из библиотеки typing в Python

2.0 Middle🔥 231 комментариев
#Безопасность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Да, активно использую Generics

Generics из typing — это один из самых мощных инструментов для написания типобезопасного и гибкого кода на Python. Я использую их повседневно при работе с контейнерами, функциями и классами.

Основные применения

Контейнеры с типизацией

from typing import List, Dict, Set, Tuple

# Перечисляем тип элементов контейнера
users: List[str] = ["Alice", "Bob"]
scores: Dict[str, int] = {"Alice": 100, "Bob": 85}
usernames: Set[str] = {"Alice", "Bob"}
coords: Tuple[int, int] = (10, 20)

Функции с параметрами-типами

from typing import TypeVar, Generic

T = TypeVar("T")  # Переменная типа

def get_first(items: List[T]) -> T:
    """Возвращает первый элемент, сохраняя тип."""
    return items[0]

# IDE поймёт, что result — это str
result: str = get_first(["hello", "world"])

Собственные Generic классы

from typing import Generic, TypeVar

T = TypeVar("T")

class Stack(Generic[T]):
    def __init__(self):
        self.items: List[T] = []
    
    def push(self, item: T) -> None:
        self.items.append(item)
    
    def pop(self) -> T:
        return self.items.pop()

# Использование
int_stack: Stack[int] = Stack()
int_stack.push(42)
value: int = int_stack.pop()

Сложные сценарии

Ограничения типов (Bounded TypeVar)

from typing import TypeVar

Comparable = TypeVar("Comparable", int, float, str)

def max_value(a: Comparable, b: Comparable) -> Comparable:
    return a if a > b else b

Multiple constraints

K = TypeVar("K", str, int)  # Ключ может быть str или int
V = TypeVar("V")            # Значение — любого типа

class Cache(Generic[K, V]):
    def __init__(self):
        self._data: Dict[K, V] = {}

Python 3.9+ синтаксис

С Python 3.9 можно использовать встроенные типы напрямую без typing:

# Старый способ (Python < 3.9)
from typing import List, Dict
users: List[str] = []

# Новый способ (Python 3.9+)
users: list[str] = []
scores: dict[str, int] = {}

Реальный пример: Repository паттерн

from typing import Generic, TypeVar, List, Optional
from sqlalchemy.orm import Session

T = TypeVar("T")

class Repository(Generic[T]):
    def __init__(self, db: Session, model: type[T]):
        self.db = db
        self.model = model
    
    def get_all(self) -> List[T]:
        return self.db.query(self.model).all()
    
    def get_by_id(self, id: int) -> Optional[T]:
        return self.db.query(self.model).filter(self.model.id == id).first()
    
    def create(self, obj: T) -> T:
        self.db.add(obj)
        self.db.commit()
        return obj

class User:
    id: int
    name: str

user_repo: Repository[User] = Repository(db, User)
users: List[User] = user_repo.get_all()

Преимущества

  • IDE поддержка: автодополнение и проверка типов работают правильно
  • Меньше ошибок: IDE и mypy ловят типобезопасность на этапе разработки
  • Документация: код самодокументируется
  • Переиспользуемость: один Generic класс работает с любыми типами

Когда использовать

Я применяю Generics в:

  • Структурах данных (стеки, очереди, деревья)
  • Repository/DAO паттернах
  • Обёртках для API клиентов
  • Функциях-утилитах высокого уровня

Generics — это не просто best practice, это необходимость при написании масштабируемого кода.