Как в аннотациях Python описать обобщённые типы — TypeVar, Generic, Protocol?
- Что такое TypeVar?
- Как mypy проверяет типы, если Python их игнорирует?
TypeVar — параметр типа: функция first(xs: list[T]) -> T сохраняет связь «что пришло, то и вернулось». Generic — обобщённый класс. С Python 3.12 — новый синтаксис: def first[T](xs: list[T]) -> T и class Box[T]. Проверяют их mypy и pyright, интерпретатор аннотации не проверяет.
- Ограничения: bound=Comparable или набор типов TypeVar("T", int, str)
- Union через |, Optional[X] = X | None (3.10)
- Pydantic и FastAPI читают аннотации во время выполнения — там они влияют на поведение
А ещё Any отключает проверку; object — безопасный «что угодно»
Подробно
Без TypeVar функция def first(xs: list) -> object теряет тип: first(["a"]).upper() — ошибка проверки. С параметром типа анализатор знает, что вернётся str.
Синтаксис по версиям: до 3.12 — T = TypeVar("T") и class Box(Generic[T]); с 3.12 — параметры в квадратных скобках прямо в объявлении (PEP 695), type Alias = ... для псевдонимов.
Вариантность: list[int] не подтип list[object] (инвариантен, потому что изменяем), а Sequence[int] — подтип Sequence[object] (ковариантен, только чтение). Это та же идея, что PECS в Java.
Практика: проверка в CI (mypy --strict или pyright) на новом коде, постепенное включение в старом; reveal_type() показывает выведенный тип.
Пример
from typing import Protocol
def first[T](items: list[T]) -> T: # Python 3.12
return items[0]
class SupportsLess(Protocol):
def __lt__(self, other, /) -> bool: ...
def max_of[T: SupportsLess](a: T, b: T) -> T:
return b if a < b else a
class Repo[T]:
def get(self, id: int) -> T | None: ...Что хотят услышать
- Зачем TypeVar и Generic.
- Новый синтаксис 3.12.
- Кто проверяет аннотации.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✓TypeVar связывает тип входа и выхода, Generic — обобщённые классы; проверяют mypy и pyright
- ✗TypeVar проверяется интерпретатором при каждом вызове функции, а Generic ускоряет работу обобщённых классов
- ✗Синтаксис def first[T](...) появился в Python 3.6
- ✗TypeVar можно использовать только в классах
Разбор темы
- Аннотации типов, mypy и Pydantic
Что дают аннотации и кто их проверяет, как аннотировать коллекции, Optional и объединения, обобщённые типы, mypy в проекте, проверка данных Pydantic.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.