Нелокальный оператор Python - PullRequest
       31

Нелокальный оператор Python

274 голосов
/ 11 августа 2009

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

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

Ответы [ 9 ]

391 голосов
/ 11 августа 2009

Сравните это, не используя 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() 'x теперь также outer()' 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
79 голосов
/ 11 августа 2009

Короче говоря, он позволяет назначать значения переменной во внешней (но не глобальной) области. Смотрите PEP 3104 для всех кровавых деталей.

37 голосов
/ 11 августа 2009

Поиск в Google "python нелокальный" обнаружил предложение, 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

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

14 голосов
/ 04 августа 2011

помощь ( 'нелокальной') nonlocal заявление


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

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

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

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

Смотри также:

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

Похожие разделы справки: global, NAMESPACES

Источник: Справочник по языку Python

14 голосов
/ 05 декабря 2010

@ ooboo:

Требуется тот, который «ближе всего» к исходной точке исходного кода. Это называется «Лексическое определение объема» и является стандартным для> 40 лет.

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

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

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

3 голосов
/ 06 мая 2015
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)
2 голосов
/ 04 августа 2011

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

1 голос
/ 21 марта 2018

Цитата из 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
0 голосов
/ 21 марта 2018

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

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)
...