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

Что такое строгая типизация?

1.2 Junior🔥 131 комментариев
#Python Core

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

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

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

# Строгая типизация

Строгая типизация (Strong Typing) — это подход программирования, при котором переменная, функция или выражение имеют чётко определённый тип, и операции над значениями разных типов запрещены или требуют явного преобразования. Это контрастирует со слабой типизацией, где тип проверяется минимально.

Ключевые концепции

Строгая типизация предотвращает:

  • Неявные преобразования типов
  • Работу с неопределённым типом
  • Логические ошибки из-за типов
  • Неожиданное поведение при операциях

Строгая vs Слабая типизация

Слабая типизация (JavaScript)

// JavaScript позволяет странные преобразования
var x = "5" + 3;       // "53" (строка + число = строка)
var y = "5" - 3;       // 2 (строка преобразуется в число)
var z = "hello" * 2;   // NaN (нет значимого преобразования)

function divide(a, b) {
    return a / b;  // a и b могут быть чем угодно!
}

console.log(divide("10", "2"));   // 5 (неожиданно работает)
console.log(divide("hello", 2));  // NaN

Строгая типизация (Python 3.5+ с hints, TypeScript, Java)

# Python с типизацией
def divide(a: int, b: int) -> int:
    """Функция требует целые числа"""
    if b == 0:
        raise ValueError("Division by zero")
    return a // b

# Статический анализ (mypy) выдаст ошибку
result = divide("10", "2")  # Type error: str is not int
result = divide(10, 2)       # OK

Строгая типизация в Python

Python 3.5+ поддерживает type hints для строгой типизации:

from typing import List, Dict, Optional, Union, Callable
from dataclasses import dataclass

# Базовые типы
def greet(name: str) -> str:
    """Функция требует строку и возвращает строку"""
    return f"Hello, {name}!"

# Сложные типы
def process_items(items: List[int]) -> Dict[str, int]:
    """Функция работает со списком целых чисел"""
    return {
        "count": len(items),
        "sum": sum(items),
        "avg": sum(items) // len(items) if items else 0
    }

# Опциональные типы
def find_user(user_id: int) -> Optional[Dict[str, str]]:
    """Может вернуть None"""
    if user_id == 1:
        return {"id": "1", "name": "Alice"}
    return None

# Union типы
def convert_to_string(value: Union[int, float, str]) -> str:
    """Принимает несколько типов"""
    return str(value)

# Callable для функций
def apply_operation(
    x: int, y: int, 
    operation: Callable[[int, int], int]
) -> int:
    """Функция принимает другую функцию"""
    return operation(x, y)

result = apply_operation(5, 3, lambda a, b: a + b)  # 8

Проверка типов: Static vs Runtime

Статическая проверка (mypy, pyright, pydantic)

# mypy проверит эту ошибку ДО выполнения кода
def add(a: int, b: int) -> int:
    return a + b

result = add("5", 3)  # mypy error: Argument 1 to "add" has incompatible type

# Запуск mypy
# $ mypy script.py

Runtime проверка (Pydantic)

from pydantic import BaseModel, ValidationError

class User(BaseModel):
    id: int
    name: str
    email: str

# Pydantic проверит типы при создании объекта
try:
    user = User(id="123", name="Alice", email="alice@example.com")
    # id автоматически преобразуется в int
    print(user.id, type(user.id))  # 123 <class 'int'>
except ValidationError as e:
    print(f"Validation error: {e}")

# Ошибочные данные
try:
    invalid = User(id="not_a_number", name="Bob", email="bob@example.com")
except ValidationError as e:
    print(f"Error: {e}")

Практический пример: Банковская система

from typing import List, Optional
from dataclasses import dataclass
from decimal import Decimal
from datetime import datetime

@dataclass
class Transaction:
    amount: Decimal
    description: str
    timestamp: datetime

class BankAccount:
    def __init__(self, account_id: int, owner: str, balance: Decimal = Decimal(0)):
        self._account_id: int = account_id
        self._owner: str = owner
        self._balance: Decimal = balance
        self._transactions: List[Transaction] = []
    
    def deposit(self, amount: Decimal) -> None:
        """Строгая типизация предотвращает ошибки"""
        if amount <= 0:
            raise ValueError("Amount must be positive")
        
        self._balance += amount
        transaction = Transaction(
            amount=amount,
            description="Deposit",
            timestamp=datetime.now()
        )
        self._transactions.append(transaction)
    
    def withdraw(self, amount: Decimal) -> bool:
        """Возвращает bool и требует Decimal"""
        if amount > self._balance:
            return False
        
        self._balance -= amount
        transaction = Transaction(
            amount=-amount,
            description="Withdrawal",
            timestamp=datetime.now()
        )
        self._transactions.append(transaction)
        return True
    
    def get_balance(self) -> Decimal:
        """Возвращает строго типизированное значение"""
        return self._balance
    
    def get_transactions(self) -> List[Transaction]:
        """Возвращает список транзакций"""
        return self._transactions.copy()
    
    def transfer_to(self, other: 'BankAccount', amount: Decimal) -> bool:
        """Работает только с BankAccount объектами"""
        if self.withdraw(amount):
            other.deposit(amount)
            return True
        return False

# Использование
account1 = BankAccount(1, "Alice", Decimal("1000"))
account2 = BankAccount(2, "Bob", Decimal("500"))

account1.transfer_to(account2, Decimal("100"))

# Это вызовет Type Error (mypy)
# account1.transfer_to(account2, "100")  # Type Error: str is not Decimal

Преимущества строгой типизации

  1. Безопасность — compiler/linter ловит ошибки до runtime
  2. Читаемость — код явно показывает типы параметров
  3. IDE поддержка — автодополнение работает лучше
  4. Документация — типы служат документацией
  5. Рефакторинг — легче менять код с уверенностью
  6. Performance — статически типизированный код может быть оптимизирован

Недостатки

  1. Verbosity — больше кода на написание
  2. Learning curve — нужно учить систему типов
  3. Может замедлить разработку — начально пишешь медленнее

Best Practices в Python

# ✅ Всегда типизируй функции
def process_data(data: List[Dict[str, int]]) -> Optional[str]:
    pass

# ❌ Не используй слишком общие типы
def bad_function(data: list) -> dict:  # Слишком общо!
    pass

# ✅ Используй Union для нескольких типов
def convert(value: Union[int, float]) -> str:
    pass

# ✅ Используй Literal для ограниченного набора значений
from typing import Literal

def set_status(status: Literal["pending", "approved", "rejected"]) -> None:
    pass

# ✅ Используй TypedDict для структурированных данных
from typing import TypedDict

class UserDict(TypedDict):
    id: int
    name: str
    email: str

Инструменты для проверки типов

# mypy — статическая проверка типов
mypy script.py

# pyright (от Microsoft) — более быстрая проверка
pyright script.py

# pydantic — runtime валидация
pip install pydantic

# Встроить в IDE (VS Code, PyCharm)
# Они автоматически проверяют типы при редактировании

Заключение

Строгая типизация в Python — это мощный инструмент для написания надёжного и безопасного кода. Используй type hints в своих проектах, это значительно улучшит качество и поддерживаемость кода.