Замыкание и область видимости переменной в проблеме python 3.x вызывает у меня замешательство - PullRequest
1 голос
/ 28 мая 2020

Я использую Python 3.7.0 и провожу несколько экспериментов, чтобы понять тонкости областей видимости переменных, но я все еще не понимаю этого поведения.

Когда я выполняю этот код:

def f():
    x=0
    def g():y=x+1;x=y
    return g
f()()

Я получаю UnboundLocalError: локальная переменная 'x', на которую ссылаются перед назначением

Однако, когда я выполняю это:

def f():
   x=0
   def g():y=x+1
   return g
f()()

Все работает нормально. И даже этот:

def f():
   x=0
   def g():x=1
   return g
f()()

Тоже нормально работает. Итак, я сбит с толку. Мне кажется, что если присвоение значения 1 нелокальной переменной x в функции g отлично работает в одиночку и, с другой стороны, если присвоить выражение, содержащее x, локальной переменной y в функция g также работает нормально, тогда обе инструкции y=x+1 и x=y должны работать. Я не понимаю, что вызывает ошибку. Я чувствую, что мне не хватает чего-то фундаментального в моем понимании поведения Python.

1 Ответ

0 голосов
/ 29 мая 2020

Я возьму на себя опрометчивую трещину. В следующем коде:

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        y = x + 1
        x = y  # assignment makes this x local to g()

    return g

f()()

Присвоение x внутри g() заставляет его быть локальной переменной g(). Таким образом, первая строка вызывает ошибку при доступе к значению неназначенного локального. Я считаю, что это «назначение делает его локальным» logi c не следует за ходом вашей программы - функция рассматривается как единое целое, чтобы сделать это определение, а затем код просматривается строка за строкой.

Вы можете получить доступ к любой переменной в области видимости из функции, но вы можете установить только локальные переменные. Если вы не объявили переменную, которую назначаете, как global или nonlocal:

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        nonlocal x

        y = x + 1
        x = y  # x is declared to come from a nonlocal scope

    return g

f()()

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

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        y = x + 1  # x comes from an outer scope

    return g

f()()

Наконец, ваш третий пример такой же, как и первый, без ошибки использования неназначенной локальной переменной:

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        x = 1  # assignment makes this x local to g()

    return g

f()()

Мне кажется, что если присвоение значения 1 нелокальной переменной x в функции g работает нормально только

Как вы определили, что переназначение x в f() нормально работало?

...