Почему я не могу перезаписать значение аргумента внешней функции, если я использую эту переменную в операторе if? - PullRequest
2 голосов
/ 10 марта 2020

Я писал декоратор, который инициализируется с аргументом, и я попытался установить этот аргумент на None по умолчанию, а затем проверить, является ли этот аргумент is None, и если да, то argument = some_default_value. Я выкинул проблему, с которой столкнулся:

Этот код работает (печатает None):

def outer(arg=None):
    def inner():
        print(arg)
    inner()

outer()

и работает этот код (печатает 22):

def outer(arg=None):
    def inner():
        arg = 22
        print(arg)
    inner()

outer()

Этот код не:

def outer(arg=None):
    def inner():
        if arg is None:
            arg = 22
        print(arg)
    inner()

outer()

Я получаю следующую ошибку:

Traceback (most recent call last):
  File "test.py", line 8, in <module>
    outer()
  File "test.py", line 6, in outer
    inner()
  File "test.py", line 3, in inner
    if arg is None:
UnboundLocalError: local variable 'arg' referenced before assignment

Почему используется переменная arg в if оператор make Python решает, что он должен быть определен в этой области, а не во внешней области?

1 Ответ

3 голосов
/ 10 марта 2020

Область действия переменной определяется при определении функции. Присваивая arg, вы делаете arg локальной переменной во всей области действия, локальной к inner, что означает, что if arg is None теперь проверяет пока еще не определенную локальную переменную arg, а не определенную нелокальную переменную на outer. (Другими словами, присутствие оператора присваивания в теле функции делает имя локальным, а не фактическое выполнение оператора, которое создает переменная с таким именем.)

Вы можете исправить это, объявив arg нелокальным в теле inner:

def outer(arg=None):
    def inner():
        nonlocal arg

        if arg is None:
            arg = 22
        print(arg)
    inner()

outer()

, хотя имейте в виду, что изменение в arg виден и после вызова inner, потому что это локальная переменная outer arg, которую вы изменили.

...