x = 1
в func2
не является свободной переменной .Это просто еще один местный житель;вы привязываетесь к имени, а имена, к которым привязаны, по умолчанию являются локальными, если вы не укажете Python иначе.
Из той же модели исполнения документации :
Если имя связано в блоке, оно является локальной переменной этого блока, если не объявлено как nonlocal
или global
. [...] Если переменная используется в блоке кода, но не определена там, она является свободной переменной.
(Выделение жирным шрифтом )
Вы связали имя в блоке с x = 1
, поэтому оно является локальной переменной в этом блоке и не может быть свободной переменной.Таким образом, найденный вами раздел неприменим, потому что он применим только к свободным переменным:
Если ближайшая включающая область действия для свободной переменной содержит оператор global
,Свободная переменная рассматривается как глобальная.
Вы не должны связывать x
в func2()
, потому что только имена, которые не в области видимости, являются свободными переменными.
Так что это работает:
>>> def func1():
... global x
... x = 1
... def func2():
... print(x) # x is a free variable here
... func2()
...
>>> func1()
1
>>> x
1
x
в func2
теперь является свободной переменной;он не определен в области действия func2
, поэтому выбирает его из родительской области.Здесь родительская область действия func1
, но x
помечена как глобальная, поэтому, когда читает x
для функции print()
, используется глобальное значение.
Сравните этос x
не помеченным как глобальное в func1
:
>>> def func1():
... x = 1
... def func2():
... print(x) # x is free variable here, now referring to x in func1
... func2()
...
>>> x = 42
>>> func1()
1
Здесь глобальное имя x
установлено на 42
, но это не влияет на то, что печатается.x
в func2
является свободной переменной, но родительская область func1
имеет только x
в качестве локального имени.
Становится все более интересным при добавленииновая внешняя область видимости, где x
равен все еще локально :
>>> def outerfunc():
... x = 0 # x is a local
... def func1():
... global x # x is global in this scope and onwards
... def func2():
... print('func2:', x) # x is a free variable
... func2()
... print('outerfunc:', x)
... func1()
...
>>> x = 42
>>> outerfunc()
outerfunc: 0
func2: 42
>>> x = 81
>>> outerfunc()
outerfunc: 0
func2: 81
x
в outerfunc
ограничен, поэтому не является свободной переменной.Поэтому он является локальным в этой области.Однако в func1
объявление global x
помечает x
как глобальное во вложенной области.В func2
x
это свободная переменная, и по утверждению, которое вы нашли, она обрабатывается как глобальная.