Нелокальное утверждение Python
При чем тут Питон nonlocal
заявление сделать (в Python 3.0 и позже)?
Там нет документации на официальном сайте Python и help("nonlocal")
тоже не работает.
10 ответов
Сравните это, не используя nonlocal
:
x = 0
def outer():
x = 1
def inner():
x = 2
print("inner:", x)
inner()
print("outer:", x)
outer()
print("global:", x)
# inner: 2
# outer: 1
# global: 0
На это, используя nonlocal
, где inner()
"s x
сейчас тоже outer()
"s x
:
x = 0
def outer():
x = 1
def inner():
nonlocal x
x = 2
print("inner:", x)
inner()
print("outer:", x)
outer()
print("global:", x)
# inner: 2
# outer: 2
# global: 0
Если бы мы должны были использовать
global
это будет связыватьx
к правильно "глобальному" значению:x = 0 def outer(): x = 1 def inner(): global x x = 2 print("inner:", x) inner() print("outer:", x) outer() print("global:", x) # inner: 2 # outer: 1 # global: 2
Короче говоря, он позволяет присваивать значения переменной во внешней (но не глобальной) области. См PEP 3104 для всех кровавых деталей.
Поиск в Google по запросу "python nonlocal" обнаружил предложение PEP 3104, которое полностью описывает синтаксис и обоснование этого утверждения. короче говоря, он работает точно так же, как global
оператор, за исключением того, что он используется для ссылки на переменные, которые не являются ни глобальными, ни локальными для функции.
Вот краткий пример того, что вы можете сделать с этим. Счетчик генератора может быть переписан, чтобы использовать его так, чтобы он больше походил на идиомы языков с замыканиями.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
Очевидно, вы можете написать это как генератор, например:
def counter_generator():
count = 0
while True:
count += 1
yield count
Но хотя это совершенно идиоматический питон, похоже, что первая версия будет немного более очевидной для начинающих. Правильное использование генераторов путем вызова возвращаемой функции является распространенной ошибкой. Первая версия явно возвращает функцию.
@ooboo:
Требуется тот, который "ближе всего" к исходной точке исходного кода. Это называется "Лексическое определение объема" и является стандартным для>40 лет.
Члены класса Python действительно в словаре под названием __dict__
и никогда не будет достигнут лексическим ограничением.
Если вы не укажете nonlocal
но делай x = 7
, он создаст новую локальную переменную "x". Если вы укажете nonlocal
, он найдет "ближайший" "х" и присвоит ему. Если вы укажете nonlocal
и нет "х", это даст вам сообщение об ошибке.
Ключевое слово global
мне всегда казалось странным, так как он с радостью игнорирует все остальные "х", кроме самого внешнего. Weird.
помощь ("нелокальная")
nonlocal
заявлениеnonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
nonlocal
оператор заставляет перечисленные идентификаторы ссылаться на ранее связанные переменные в ближайшей области видимости. Это важно, потому что поведение по умолчанию для привязки - сначала искать в локальном пространстве имен. Оператор позволяет инкапсулированному коду связывать переменные вне локальной области, кроме глобальной (модульной) области.Имена, перечисленные в
nonlocal
заявление, в отличие от перечисленных вglobal
оператор, должен ссылаться на ранее существовавшие привязки во вложенной области (область, в которой должна быть создана новая привязка, не может быть определена однозначно).Имена, перечисленные в
nonlocal
Оператор не должен вступать в противоречие с ранее существовавшими привязками в локальной области видимости.Смотрите также:
PEP 3104 - доступ к именам во внешних областях
Спецификация дляnonlocal
заявление.Связанные разделы справки: глобальный, NAMESPACES
Источник: Python Language Reference
Цитата из Python 3
Нелокальный оператор заставляет перечисленные идентификаторы ссылаться на ранее связанные переменные в ближайшей охватывающей области, исключая глобальные переменные.
Как сказано в ссылке, в случае нескольких вложенных функций изменяется только переменная в ближайшей вмещающей функции:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
x = 2
innermost()
if x == 3: print('Inner x has been modified')
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Inner x has been modified
"Ближайшая" переменная может находиться на расстоянии нескольких уровней:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Outer x has been modified
Но это не может быть глобальная переменная:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
inner()
x = 0
outer()
if x == 3: print('Global x has been modified')
# SyntaxError: no binding for nonlocal 'x' found
a = 0 #1. global variable with respect to every function in program
def f():
a = 0 #2. nonlocal with respect to function g
def g():
nonlocal a
a=a+1
print("The value of 'a' using nonlocal is ", a)
def h():
global a #3. using global variable
a=a+5
print("The value of a using global is ", a)
def i():
a = 0 #4. variable separated from all others
print("The value of 'a' inside a function is ", a)
g()
h()
i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)
Мое личное понимание "нелокального" утверждения (и, простите меня, поскольку я новичок в Python и программировании в целом) заключается в том, что "нелокальный" - это способ использовать глобальную функциональность внутри итеративных функций, а не тело самого кода., Глобальное утверждение между функциями, если хотите.
В документации сказано ниже:
Оператор nonlocal заставляет перечисленные идентификаторы ссылаться на ранее связанные переменные в ближайшей охватывающей области, исключая глобальные. ...
Так, например,nonlocal foo
вinner()
может получить доступ к нелокальной переменной
foo = 10
вmiddle()
но не нелокальная переменная
foo = 5
in или глобальная переменная
foo = 0
снаружиouter()
как показано ниже:
foo = 0 # <- ✖
def outer():
foo = 5 # <- ✖
def middle():
foo = 10 # <- 〇
def inner():
nonlocal foo # Here
foo += 1
print(foo) # 11
inner()
middle()
outer()
С помощью "нелокальных" внутренних функций (т. е. вложенных внутренних функций) можно получить разрешение на чтение и " запись " для этой конкретной переменной внешней родительской функции. И нелокальный можно использовать только внутри внутренних функций, например:
a = 10
def Outer(msg):
a = 20
b = 30
def Inner():
c = 50
d = 60
print("MU LCL =",locals())
nonlocal a
a = 100
ans = a+c
print("Hello from Inner",ans)
print("value of a Inner : ",a)
Inner()
print("value of a Outer : ",a)
res = Outer("Hello World")
print(res)
print("value of a Global : ",a)