Нелокальная инструкция Python

что делает Python nonlocal оператор do (в Python 3.0 и более поздних версиях)?

на официальном сайте Python нет документации и help("nonlocal") также не работает.

9 ответов


сравните это, не используя 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

но хотя это совершенно идиоматический python, кажется, что первая версия будет немного более очевидной для начинающих. Правильное использование генераторов, вызывая возвращаемую функцию, является общей точкой путаницы. Первая версия явно возвращает функцию.


помочь ("нелокального") The nonlocal сообщении


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

The nonlocal оператор заставляет перечисленные идентификаторы ссылаться на ранее связанные переменные в ближайшей охватывающей области. Это важно, потому что поведение по умолчанию для привязки к поиск сначала локальное пространство имен. Оператор позволяет инкапсулировать код в rebind переменные вне локальной области, кроме глобальной (модуля) объем.

имена перечислены в nonlocal оператор, в отличие от перечисленных в global оператор, должен ссылаться на ранее существующие привязки в охватывающая область (область, в которой должна быть создана новая привязка нельзя определить однозначно).

имена, перечисленные в nonlocal оператор не должен сталкиваться с pre- существующие привязки в локальной области.

Читайте также:

PEP 3104 - доступ к именам во внешних областях
Спецификация для nonlocal заявление.

связанные разделы справки: global, пространства имен

источник: Ссылка На Язык Python


@ooboo:

он принимает один "ближайший" к точке отсчета в исходном коде. Это называется "лексическим охватом" и является стандартным для >40 лет.

члены класса Python действительно находятся в словаре под названием __dict__ и никогда не будет достигнуто лексическим охватом.

если вы не укажете nonlocal но x = 7, он создаст новую локальную переменную "x". Если вы укажете nonlocal, он найдет "ближайший "" x " и назначит его. Если вы укажите nonlocal и нет "x", это даст вам сообщение об ошибке.

ключевое слово global мне всегда казалось странным, так как он с радостью проигнорирует все остальные "x", кроме самого внешнего. Странный.


мое личное понимание" нелокального " утверждения (и извините меня, поскольку я новичок в Python и программировании в целом) заключается в том, что "нелокальный" - это способ использовать глобальную функциональность в итерационных функциях, а не тело самого кода. Глобальный оператор между функциями, если хотите.


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)

С "нелокальными" внутренними функциями (т. е. вложенными внутренними функциями) можно читать &'написать'для этой конкретной переменной внешней родительской функцией. А нелокальные можно использовать только внутри внутренних функций например:

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)

цитата 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