Локальные функции в Python

В следующем коде Python я получаю UnboundLocalError. Как я понимаю, локальные функции разделяют локальные переменные содержащейся функции, но это вряд ли имеет место здесь. Я признаю, что a является неизменяемым значением в этом контексте, но это не должно быть проблемой.

def outer():
    a = 0
    def inner():
        a += 1
    inner()
outer()

Казалось бы, внутренняя функция получила копии всех ссылок в родительской функции, так как я не получаю исключение UnboundLocalError, если значение a завернуто в изменяемый тип.

Кто-нибудь может прояснить поведение здесь и указать мне на соответствующую документацию на Python?

Ответ 1

Я считаю, что вы правы, рассматривая это как проблему "изменчивости". Хотя код, который вы опубликовали, выдает "UnboundLocalError", следующий код не делает:

def outer():
    a = 0
    def inner():
        print a
    inner()
outer()

Python не позволяет переназначить значение переменной из внешней области во внутренней области (если вы не используете ключевое слово "global", которое в этом случае не применяется).

Обратите внимание на нижнюю часть документации "classes" в этой документации Python 2.6.2:

9.2. Области и пространства имен Python

[& hellip;] Если имя объявлено глобальным, то все ссылки и назначения идут непосредственно к среднему охвату, содержащему глобальные имена модулей. В противном случае все переменные, найденные вне самой внутренней области, только для чтения (попытка написать такую ​​переменную просто создаст новая локальная переменная в самой внутренней области, оставив тождественно именованная внешняя переменная не изменилась).

"UnboundLocalError" - это потому, что ваша функция фактически объявляет новую переменную с именем "a" , а затем сразу же пытается выполнить операцию "+ =", но это не удается, потому что "a" еще не имеет значения. (Посмотрите "a + = 1" как "a = a + 1", и вы можете увидеть проблему, если "a" - undefined).

В общем, если вы захотите изменить "a" , то, как люди обычно обходят его, нужно использовать изменяемый тип, чтобы передать "a" (например, список или словарь). Вы можете изменить "a" через содержимое изменяемого типа (как вы, вероятно, заметили в своем тестировании с помощью этой настройки).

Надеюсь, что это поможет!

Ответ 2

Попробуйте привязать переменную в качестве аргумента.

def outer():
    a = 0
    def inner(a=a):
        a += 1

    inner()

outer()

Я попытаюсь выкопать соответствующие документы.

изменить

Поскольку вы хотите, чтобы внутренняя функция имела побочный эффект внешней области, вам нужно использовать изменяемый тип данных, например список. Целые числа и строки являются неизменными.

def outer():
    a = [0]
    def inner():
        a[0] += 1
    inner()
    print a[0]
outer()

Ответ 3

Вы должны указать свою переменную как нелокальную, чтобы сохранить ее в закрытии, поэтому определение должно быть таким:

def outer():
a = 0
def inner():
    nonlocal a
    a += 1
inner()