Зачем нужна типизация
Type hints в Python — это аннотации типов, которые помогают:
▸До и после
1# Без type hints2def add(a, b):3 return a + b45# С type hints6def add(a: int, b: int) -> int:7 return a + b
Основные типы
▸Примитивы
1name: str = "Alice"2age: int = 253height: float = 1.754is_active: bool = True
▸Коллекции
1from typing import List, Dict, Tuple, Set, Optional23# Списки4numbers: List[int] = [1, 2, 3]5names: list[str] = ["Alice", "Bob"] # Python 3.9+67# Словари8user: Dict[str, int] = {"age": 25}9scores: dict[str, float] = {"math": 95.5} # Python 3.9+1011# Кортежи12point: Tuple[int, int] = (10, 20)13point: tuple[int, int] = (10, 20) # Python 3.9+1415# Множества16unique: Set[int] = {1, 2, 3}1718# Опциональные значения19name: Optional[str] = None # str | None
▸Union и Literal
1from typing import Union, Literal23# Union — одно из типов4value: Union[int, str] = 425value: int | str = 42 # Python 3.10+67# Literal — конкретные значения8status: Literal["active", "inactive", "pending"] = "active"
Функции
▸Аргументы и возвращаемые значения
1def greet(name: str) -> str:2 return f"Hello, {name}"34def process(data: list[int], factor: float = 1.0) -> list[float]:5 return [x * factor for x in data]
▸Callable
1from typing import Callable23def apply(func: Callable[[int, int], int], a: int, b: int) -> int:4 return func(a, b)56def add(a: int, b: int) -> int:7 return a + b89result = apply(add, 2, 3) # 5
Generics
▸Определение generic-типов
1from typing import TypeVar, Generic23T = TypeVar('T')45class Stack(Generic[T]):6 def __init__(self) -> None:7 self.items: list[T] = []89 def push(self, item: T) -> None:10 self.items.append(item)1112 def pop(self) -> T:13 return self.items.pop()1415# Использование16int_stack: Stack[int] = Stack()17int_stack.push(42)
▸Ограничение generic-типов
1from typing import TypeVar23T = TypeVar('T', int, float)45def sum_values(values: list[T]) -> T:6 return sum(values) # type: ignore78sum_values([1, 2, 3]) # OK9sum_values([1.0, 2.0]) # OK10sum_values(["a", "b"]) # Ошибка!
Протоколы (Structural Subtyping)
1from typing import Protocol23class Drawable(Protocol):4 def draw(self) -> None: ...56class Circle:7 def draw(self) -> None:8 print("Drawing circle")910class Square:11 def draw(self) -> None:12 print("Drawing square")1314def draw_shape(shape: Drawable) -> None:15 shape.draw()1617draw_shape(Circle()) # OK18draw_shape(Square()) # OK
TypedDict
1from typing import TypedDict23class UserDict(TypedDict):4 name: str5 age: int6 email: str78def process_user(user: UserDict) -> str:9 return f"{user['name']} ({user['age']})"1011# Использование12user: UserDict = {13 "name": "Alice",14 "age": 25,15 "email": "alice@test.com"16}
mypy: статический анализ
▸Установка и запуск
1pip install mypy23# Проверка файла4mypy script.py56# Проверка проекта7mypy src/
▸Конфигурация (mypy.ini)
1[mypy]2python_version = 3.113strict = True4warn_return_any = True5warn_unused_configs = True67[mypy-third_party_lib.*]8ignore_missing_imports = True
▸Игнорирование ошибок
1result = some_untyped_function() # type: ignore23# Или на уровне модуля4# mypy: ignore-errors
Callable и возвращаемые типы
1from typing import Callable, Awaitable23# Синхронная функция4handler: Callable[[str, int], str] = lambda name, age: f"{name}: {age}"56# Асинхронная функция7async_handler: Callable[[str], Awaitable[str]] = async_lambda name: f"Hello, {name}"
Практические советы
▸Постепенная типизация
1# Начните с функций2def process(data: list[int]) -> list[int]:3 return [x * 2 for x in data]45# Потом добавляйте типы переменных6result: list[int] = process([1, 2, 3])78# Используйте Any как временное решение9from typing import Any10legacy_data: Any = get_legacy_data()
▸Паттерны типизации
1# Type guard2def is_string(value: object) -> bool:3 return isinstance(value, str)45def process(value: str | int) -> str:6 if isinstance(value, str):7 return value.upper()8 return str(value)
Заключение
Type hints делают Python-код более надёжным и поддерживаемым. Для собеседования важно знать основные типы, generics, протоколы и как использовать mypy. Постепенная типизация позволяет внедрять type hints в существующий код без боли.