Области видимости (Scopes) в Python

Области видимости (Scopes) в Python


Области видимости (Scopes) в Python

Определение

Область видимости (Scope) — это область кода, в которой переменная может быть использована. Python использует правило LEGB для поиска переменных:

  1. L (Local): Внутри функции.
  2. E (Enclosing): Внешние функции (для вложенных функций).
  3. G (Global): На уровне модуля.
  4. B (Built-in): Встроенные имена (например, print, len).

Правило LEGB

Python ищет переменные в следующем порядке:

x = "global"  # Global

def outer():
    x = "enclosing"  # Enclosing
    def inner():
        x = "local"  # Local
        print(x)      # "local" (Local)
    inner()

outer()
print(x)  # "global" (Global)
print(len)  # <built-in function len> (Built-in)

Ключевые слова global и nonlocal

global

Позволяет изменять глобальные переменные внутри функции.

x = 0

def change_global():
    global x
    x = 10  # Изменяет глобальную переменную

change_global()
print(x)  # 10

nonlocal

Используется во вложенных функциях для изменения переменных из внешней области.

def outer():
    x = 0
    def inner():
        nonlocal x
        x = 20  # Изменяет переменную из outer()
    inner()
    print(x)  # 20

outer()

Замыкания (Closures)

Вложенная функция “запоминает” переменные из внешней области видимости.

def counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

c = counter()
print(c())  # 1
print(c())  # 2 (сохраняет состояние count)

Функции globals() и locals()

  • globals(): Возвращает словарь глобальных переменных.
  • locals(): Возвращает словарь локальных переменных.

Можно ли их изменять?

  • globals(): Да (но осторожно!).
  • locals(): Нет (изменения могут не отразиться на реальных переменных).
def test():
    x = 10
    locals_dict = locals()
    locals_dict["x"] = 20  # Не изменит реальную x
    print(x)  # 10

test()

globals()["x"] = 30  # Изменит глобальную переменную

Область видимости переменных исключений

Переменная исключения (например, e в except Exception as e) существует только внутри блока except.

try:
    1 / 0
except ZeroDivisionError as e:
    print(e)  # Работает

print(e)  # NameError: name 'e' is not defined (в Python 3)

Исключение: Если переменная сохранена вне блока.

error = None
try:
    1 / 0
except ZeroDivisionError as e:
    error = e

print(error)  # division by zero

Примеры частых ошибок

1. Создание локальной переменной вместо изменения глобальной

x = 10

def func():
    x = 20  # Создает локальную переменную
    print(x)  # 20

func()
print(x)  # 10 (глобальная не изменилась)

2. Использование nonlocal без внешней переменной

def outer():
    def inner():
        nonlocal x  # SyntaxError: no binding for nonlocal 'x' found
        x = 10
    inner()

Заключение

  • LEGB определяет порядок поиска переменных.
  • global и nonlocal позволяют изменять переменные из внешних областей.
  • Замыкания сохраняют состояние внешних переменных.
  • globals() и locals() дают доступ к переменным, но изменять их нужно осторожно.
  • Переменные исключений недоступны вне блока except.

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