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

Область видимости переменных функции

Область видимости или scope определяет видимость имени переменной в блоке кода, в рамках которого ее можно прочитать или изменить. Если вы попытаетесь использовать что-либо, что не является в вашей области видимости, вы получите ошибку NameError. В Python есть два типа контекста: глобальный и локальный.

Определение переменной в коде происходит в результате операций связывания или присваивания.

Если переменная используется в блоке кода, но не определена в нем, то такая переменная называется свободной. Свободные переменные разрешаются (смотрите "Правила разрешение имен в Python") не в ближайшем окружающем пространстве имен, а в глобальном пространстве имен.

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

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

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

from math import ceil # область встроенных имен

def sum_func():
    # локальная область видимости функции sum_func()
    b = a * 10 # 'b'
    # 'b' - локальная переменная функции sum_func()
    # НЕ доступна для ЧТЕНИЯ в глобальной области 
    # Доступна для ЧТЕНИЯ в области видимости вложенной функции nested()
    # НЕ доступна для ИЗМЕНЕНИЯ в области видимости вложенной функции nested()
    # Здесь 'a' называется свободной переменной
    
    def nested():
        # локальная область видимости вложенной функции nested()
        z = b / 5 * a 
        # 'z' - локальная переменная вложенной функции nested()
        # НЕ доступна для ЧТЕНИЯ в глобальной области 
        # НЕ доступна для ЧТЕНИЯ в области видимости функции sum_func()
        # Здесь 'a' называется свободной переменной
        # Здесь 'b' называется нелокальной переменной
        return z
    
    return nested()


# Глобальная область видимости

a = 10 
# 'a' - глобальная переменная
# Доступна для ЧТЕНИЯ в области видимости функции sum_func()
# Доступна для ЧТЕНИЯ в области видимости вложенной функции nested()
# НЕ доступна для ИЗМЕНЕНИЯ в области видимости функции sum_func()
# НЕ доступна для ИЗМЕНЕНИЯ в области видимости вложенной функции nested()

print(sum_func())
#  напечатает 
200.0

Таким образом:

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

Избегайте затенения переменных

Если локальная переменная имеет то же имя, что и глобальная переменная или встроенная, она затеняет глобальную или встроенную переменную:

x = 10

def shadow():
    x = 5
    print(f'x=')

shadow()  
# x=5 (здесь произошло затенение глобальной переменной)

print(f'x=')
# x=10  (глобальная переменная `x` не изменилась)

Затенение может привести к неожиданному поведению, поэтому рекомендуется избегать использования одних и тех же имен переменных в разных областях.