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

⚡ Топ-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)  # аргумент не меняется!

Сообщение об ошибке: RecursionError

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

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

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

❌ Ошибка 3. Забытый return у рекурсивного вызова

# Неправильно
def factorial(n: int) -> int:
    if n == 0 or n == 1:
        return 1
    factorial(n - 1)  # результат не возвращается!

Почему возникает: без return функция возвращает None, и рекурсивные вычисления теряются.

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

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

❌ Ошибка 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. Неправильный синтаксис isinstance

# Неправильно
value = 3.14
if isinstance(value, int, float):  # TypeError
    pass

Сообщение об ошибке: TypeError: isinstance expected 2 arguments, got 3

Почему возникает: для проверки нескольких типов нужно передавать кортеж.

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

# Правильно
value = 3.14
if isinstance(value, (int, float)):
    pass

❌ Ошибка 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