🐛 Типичные ошибки

⚡ Топ-3 ошибки

  • Забыть базовый случай в рекурсии — получим RecursionError.
  • Думать, что аннотации типов вызывают ошибку при неверном типе.
  • Путать поверхностное и глубокое копирование вложенных структур.

❌ Ошибка 1. Отсутствие базового случая

# Неправильно
def factorial(n: int) -> int:
    return n * factorial(n - 1)

factorial(5)  # RecursionError

Сообщение об ошибке: RecursionError: maximum recursion depth exceeded

Почему возникает: функция бесконечно вызывает сама себя, потому что нет условия остановки.

✅ Исправление

# Правильно
def factorial(n: int) -> int:
    if n == 0 or n == 1:
        return 1
    return n * factorial(n - 1)

❌ Ошибка 2. Аргумент не приближается к базовому случаю

# Неправильно
def countdown(n: int):
    if n == 0:
        return
    print(n)
    countdown(n)  # аргумент не меняется!

countdown(5)  # RecursionError

Почему возникает: рекурсивный вызов идёт с тем же аргументом, поэтому базовый случай никогда не наступает.

✅ Исправление

# Правильно
def countdown(n: int):
    if n == 0:
        return
    print(n)
    countdown(n - 1)

❌ Ошибка 3. Ожидание, что type hints вызовут ошибку

# Неправильное понимание
def add(a: int, b: int) -> int:
    return a + b

print(add("3", "5"))  # "35" — ошибки не будет!

Почему возникает: аннотации типов не влияют на выполнение. Для проверки типов нужен статический анализатор, например mypy.

✅ Исправление понимания

# Аннотации — для IDE и mypy
# Запуск: mypy script.py

def add(a: int, b: int) -> int:
    return a + b

print(add(3, 5))  # 8

❌ Ошибка 4. Поверхностная копия вместо глубокой

# Неправильно
original = [[1, 2], [3, 4]]
copy_lst = original.copy()
copy_lst[0][0] = "X"
print(original)  # [['X', 2], [3, 4]] — оригинал изменился!

Почему возникает: copy() копирует только верхний уровень списка, а вложенные списки остаются общими.

✅ Исправление

# Правильно
from copy import deepcopy

original = [[1, 2], [3, 4]]
copy_lst = deepcopy(original)
copy_lst[0][0] = "X"
print(original)  # [[1, 2], [3, 4]]

❌ Ошибка 5. Docstring не в начале функции

# Неправильно
def greet(name: str) -> str:
    x = 1
    """Возвращает приветствие."""
    return f"Hello, {name}!"

print(greet.__doc__)  # None

Почему возникает: docstring должен быть первой строкой в теле функции.

✅ Исправление

# Правильно
def greet(name: str) -> str:
    """Возвращает приветствие."""
    return f"Hello, {name}!"

print(greet.__doc__)  # Возвращает приветствие.

❌ Ошибка 6. Надежда на оптимизацию хвостовой рекурсии

# Неэффективно для больших n
def factorial_tail(n: int, acc: int = 1) -> int:
    if n == 0 or n == 1:
        return acc
    return factorial_tail(n - 1, n * acc)

factorial_tail(10000)  # RecursionError

Почему возникает: Python не оптимизирует хвостовую рекурсию, поэтому стек всё равно растёт.

✅ Исправление

# Правильно
def factorial_iterative(n: int) -> int:
    acc = 1
    while n > 1:
        acc *= n
        n -= 1
    return acc