Сообщить об ошибке.

Операторы global и nonlocal в Python

Инструкции global и nonlocal, как пользоваться

Ссылки для тех кто ищет встроенные функции globals() и locals().

Инструкция global:

Инструкция global это объявление, которое выполняется для всего текущего блока кода. Это означает, что перечисленные в инструкции переменные должны интерпретироваться как глобальные. Свободные переменные могут ссылаться на глобальные переменные с помощью global, не будучи объявленными в глобальной области.

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

Имена, перечисленные в инструкции global, не должны быть определены как аргументы функции или использоваться в целевом элементе item управления циклом for item in .... Не должны быть связаны с именем в определении класса, определении функции, оператора import или аннотации переменной.

Инструкция global, содержащийся в строке или объекте кода, переданном во встроенную функцию exec(), не влияет на блок кода, содержащий вызов функции, и на код, содержащийся в такой строке, не влияют операторы global в коде, содержащем вызов функции. То же самое относится к функциям eval() и compile().

Инструкция nonlocal:

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

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

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

Обобщая сказанное:

  • операторы global и nonlocal используются в области видимости той функции, где будет требуется изменение переменной;
  • оператор global можно использовать как в простых функциях, так и во вложенных;
  • оператор nonlocal используются только во вложенных функциях;
  • с помощью оператора global можно определить глобальную переменную из области видимости функции, которая ранее отсутствовала;
  • при использовании оператора nonlocal, переменные родительской функции должны существовать.

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

Изменение глобальной переменной внутри функции с помощью global:

# Глобальная область видимости
# Определим глобальные переменные
global_a = 0
global_b = 100

def plus():
    # Локальная область видимости функции plus()
    # Здесь НЕДОСТУПНО ИЗМЕНЕНИЕ глобальных переменных
    try:
        global_a = global_a + 5
    except:
        print('!!! Не можем изменить глобальную переменную global_a '\
            'внутри функции plus()')
    finally:
        global_a = 1
        # Здесь создалась новая локальная переменная функции plus(),
        # которая хранит свое значение только внутри функции plus()
        # и не имеет ни чего общего с глобальной переменной global_a
        # в Python это называется скрытием глобальной переменной
        print(global_a, '=> global_a - это новая локальная переменная '\
            'функции plus()')
        
    # Укажем, что global_b - глобальная, для функции plus()
    global global_b
    # Изменим глобальную переменную global_b на 100
    global_b = global_b + 100

plus()

print(global_a, '=> Глобальная переменная global_a НЕ изменилась.')
print(global_b, '=> Глобальная переменная global_b изменена '\
        'внутри функции plus()')

Создание глобальной переменной внутри функций с помощью global:

def plus():
    # Локальная область видимости функции plus()

    # global_a у нас еще ни где не определена 
    global global_a # Глобальные переменные могут отсутствовать при их создании
    global_a = 50 # Создаст переменную global_a в глобальной области видимости
    global_a = global_a - 10
    
    def nested():
        # локальная область видимости вложенной функции nested()

        # Что бы изменить глобальную переменную global_a, мы  
        # должны указать с помощью оператора global, что эта 
        # переменная для вложенной функции то же является глобальной
        global global_a
        global_a = global_a - 10

        # С помощь. оператора global можно создавать 
        # глобальные переменные, так же во вложенных функциях 
        global global_b 
        global_b = 0 # Создаст переменную global_b в глобальной области видимости
        global_b = global_b + 5
    
    # Выполним вложенную функцию
    nested()
    
    # Изменим глобальную переменную global_b, созданную 
    # во вложенной функции, для этого укажем с помощью 
    # оператора global, что эта переменная для родительской 
    # функции то же является глобальной
    global global_b
    global_b = global_b + 5
    
# вызов функции plus()
plus()

global_a = global_a + 100
print(global_a, '=> глобальная переменная global_a, созданная '\
    'в родительской функции plus() изменена в глобальной области видимости')

global_b = global_b + 50
print(global_b, '=> глобальная переменная global_b, созданная '\
    'во вложенной функции nested() изменена в глобальной области видимости')

Изменение переменной родительской функции во вложенной функции с помощью nonlocal:

def plus():
    # Локальная область видимости функции plus()
    # Определим локальные переменные функции plus()
    plus_a = 5
    plus_b = 10
    
    # Вложенная функция nested()
    def nested():
        # локальная область видимости вложенной функции nested()
        # Здесь НЕДОСТУПНО ИЗМЕНЕНИЕ локальных переменных функции plus()
        try:
            plus_a = plus_a + 5
        except:
            print('Не можем изменить локальную переменную plus_a, созданную '\
                'в функции plus(), внутри вложенной функции nested()')
        finally:
            plus_a = 1
            # Здесь создалась новая локальная переменная функции nested(),
            # которая хранит свое значение только внутри функции nested()
            # и не имеет ни чего общего с локальной переменной plus_a, которая 
            # определялась ранее в локальной области видимости функции plus()
            print(plus_a, '=> plus_a - это новая локальная переменная '\
                'в области видимости функции plus()')
        
        # Укажем, что plus_b - не локальная, для вложенной функции nested()
        nonlocal plus_b # !!! Нелокальные переменные должны существовать!
        plus_b = plus_b + 10
        print(plus_b, 'Переменная plus_b локальной области функции plus() '\
            'изменена внутри области видимости вложенной функции nested()')
        
    # вызов вложенной функции nested()
    nested()
    
    print(plus_a, '=> Локальная переменная plus_a, созданная в функции '\
        'plus() НЕ изменилась.')
    print(plus_b, '=> Локальная переменная plus_b, созданная в функции '\
            'plus() изменена внутри вложенной функции nested()')

# вызов функции plus()
plus()