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

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

33 голосов
/ 12 сентября 2009

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

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

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

Может ли кто-то уточнить здесь поведение и указать мне соответствующую документацию Python по этому вопросу?

Ответы [ 3 ]

30 голосов
/ 12 сентября 2009

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

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

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

Ознакомьтесь с нижним разделом документации "классов" в этой документации Python 2.6.2:

9,2. Области применения и пространства имен Python

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

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

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

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

10 голосов
/ 11 марта 2013

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

def outer():
a = 0
def inner():
    nonlocal a
    a += 1
inner()
9 голосов
/ 12 сентября 2009

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

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...