Типизация и проверка типов: 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].


Ресурсы для углубления 📚

Теперь твой код станет надежнее, понятнее и профессиональнее! Пиши типы — и пусть баги обходят твой код стороной 😉

Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео