Типизация и проверка типов: mypy, pyright
Почему типизация — это круто? 🎯
Python — язык с динамической типизацией, но это не значит, что типы не важны! Типизация помогает: - Ловить ошибки до запуска кода - Делать код понятнее и предсказуемее - Улучшать автодополнение в IDE
Пример без типизации:
def greet(name):
return f"Hello, {name}!"
greet(42) # Ой! Работает, но логически неверно
А теперь с типами:
def greet(name: str) -> str:
return f"Hello, {name}!"
greet(42) # mypy сразу скажет: error: Argument 1 has incompatible type "int"
Аннотации типов в Python 🏷️
С Python 3.5+ типы стали частью языка через type hints:
# Простые типы
age: int = 25
name: str = "Alice"
# Коллекции
from typing import List, Dict, Optional
def process_items(items: List[str], prices: Dict[str, float]) -> Optional[float]:
if not items:
return None
return sum(prices.get(item, 0.0) for item in items)
🔥 Pro-совет: Используй from __future__ import annotations (Python 3.7+) для отложенных аннотаций!
Mypy — статический анализатор 🕵️♂️
Mypy — самый популярный инструмент проверки типов. Установка:
pip install mypy
Пример использования:
# calculator.py
def add(a: int, b: int) -> int:
return a + b
result = add(5, "10") # Ошибка типа!
Запускаем проверку:
mypy calculator.py
Вывод:
calculator.py:4: error: Argument 2 to "add" has incompatible type "str"; expected "int"
Pyright — альтернатива от Microsoft 🚀
Pyright быстрее mypy и имеет больше возможностей. Установка:
npm install -g pyright # Да, через Node.js!
Пример конфига (pyrightconfig.json):
{
"pythonVersion": "3.10",
"typeCheckingMode": "strict"
}
Запуск:
pyright
🔥 Фишка Pyright: Лучшая поддержка pattern matching и TypeGuard!
Продвинутые техники типизации 🧙♂️
1. Типовые переменные (Generics)
from typing import TypeVar, Generic
T = TypeVar('T')
class Box(Generic[T]):
def __init__(self, content: T):
self.content = content
int_box: Box[int] = Box(42)
str_box: Box[str] = Box("hello")
2. Перегрузка функций
from typing import overload
@overload
def double(x: int) -> int: ...
@overload
def double(x: str) -> str: ...
def double(x):
return x * 2
3. Типы для callback-ов
from typing import Callable
Processor = Callable[[str, int], list[str]]
def run_processor(callback: Processor) -> None:
result = callback("test", 3)
print(result)
Как внедрить типизацию в проект? 🏗️
1. Начни с конфига:
# mypy.ini
[mypy]
python_version = 3.10
disallow_untyped_defs = True
warn_return_any = True
2. Добавь проверку в CI/CD:
# .github/workflows/checks.yml
- name: Run mypy
run: mypy .
3. Используй gradual typing — добавляй аннотации постепенно!
Ошибки и как их избегать 🚨
Частая ошибка №1: Any
from typing import Any
def process(data: Any) -> Any: # Плохо! Теряем все преимущества типов
return data * 2
✅ Решение: Используй конкретные типы или TypeVar.
Частая ошибка №2: Игнорирование None
def get_user(id: int) -> dict: # А если пользователя нет?
...
✅ Решение: Используй Optional[dict] или Union[dict, None].
Ресурсы для углубления 📚
- PEP 484 — официальная спецификация типов
- Mypy документация
- Pyright документация
- Канал Данилы Бежина про продвинутую типизацию
Теперь твой код станет надежнее, понятнее и профессиональнее! Пиши типы — и пусть баги обходят твой код стороной 😉