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

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

  1. Вызов вложенной функции снаружи внешней.
  2. Попытка изменить внешнюю переменную без nonlocal.
  3. «Позднее связывание» в циклах.
  4. Использование изменяемых значений по умолчанию в замыканиях.
  5. Путаница nonlocal и global.

❌ Ошибка 1. Вызов вложенной функции снаружи

def outer():
    def inner():
        print("Hi")
    return inner()


result = outer()
result()  # TypeError: 'NoneType' object is not callable

Почему возникает: return inner() вызывает внутреннюю функцию и возвращает её результат (None), а не саму функцию.

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

def outer():
    def inner():
        print("Hi")
    return inner  # без скобок


result = outer()
result()  # Hi

❌ Ошибка 2. Изменение внешней переменной без nonlocal

def make_counter():
    count = 0

    def increment():
        count += 1  # UnboundLocalError
        return count

    return increment

Сообщение об ошибке: UnboundLocalError: cannot access local variable 'count' where it is not associated with a value

Почему возникает: присваивание count += 1 делает count локальной для increment, но значение ещё не определено.

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

def make_counter():
    count = 0

    def increment():
        nonlocal count
        count += 1
        return count

    return increment

❌ Ошибка 3. Позднее связывание в цикле

def make_multipliers():
    return [lambda x: x * i for i in range(5)]


for func in make_multipliers():
    print(func(2))  # 8 8 8 8 8

Почему возникает: лямбда захватывает имя i, а не его значение. К моменту вызова цикл уже закончился, и i == 4.

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

def make_multipliers():
    return [lambda x, i=i: x * i for i in range(5)]


for func in make_multipliers():
    print(func(2))  # 0 2 4 6 8

Значение по умолчанию вычисляется в момент определения функции и таким образом фиксирует текущее i.

❌ Ошибка 4. Изменяемое значение по умолчанию

def make_logger(entries=[]):
    def log(message: str):
        entries.append(message)
        return entries
    return log


log_a = make_logger()
log_a("event 1")
log_b = make_logger()
print(log_b("event 2"))  # ['event 1', 'event 2']  # общий список!

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

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

def make_logger(entries: list[str] | None = None):
    if entries is None:
        entries = []

    def log(message: str):
        entries.append(message)
        return entries

    return log

❌ Ошибка 5. Путаница nonlocal и global

count = 0

def outer():
    def inner():
        nonlocal count  # SyntaxError
        count += 1
    return inner

Сообщение об ошибке: SyntaxError: no binding for nonlocal 'count' found

Почему возникает: nonlocal ищет имя только во внешних функциях, но не в глобальной области. Для глобальной переменной нужно global.

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

count = 0

def outer():
    def inner():
        global count
        count += 1
    return inner