W3docs

Область видимости в Python

Изучите область видимости Python и правило LEGB: локальная, вложенная, глобальная и встроенная области с примерами и ключевыми словами global/nonlocal.

Понимание области видимости в Python

Область видимости определяет, где имя переменной доступно и как долго оно существует. Каждое имя, которое вы создаёте — переменная, функция, класс — принадлежит ровно одной области видимости. Когда Python встречает имя, он ищет его по областям видимости в строгом порядке, пока не найдёт это имя или не выбросит NameError.

На этой странице рассматриваются:

  • Четыре уровня области видимости и правило поиска LEGB
  • Ключевые слова global и nonlocal
  • Распространённые ошибки: затенение имён, UnboundLocalError и утечка имён
  • Как проверить области видимости во время выполнения

Правило LEGB

Python разрешает имена в четырёх слоях, поиск ведётся от самого внутреннего к самому внешнему:

УровеньРасшифровкаЧто содержит
LLocal (Локальный)Имена, определённые внутри текущей функции
EEnclosing (Вложенный)Имена в любой внешней (охватывающей) функции, для вложенных функций
GGlobal (Глобальный)Имена, определённые на верхнем уровне текущего модуля
BBuilt-in (Встроенный)Имена, предустановленные Python — print, len, range, type и др.

Python останавливается на первом совпадении. Если совпадение не найдено ни в одном слое, выбрасывается NameError.

Локальная область видимости

Имя является локальным, если оно присваивается внутри функции. Оно создаётся при вызове функции и уничтожается при её возврате. Локальные имена недоступны за пределами функции.

def greet():
    message = "Hello, World!"  # local variable
    print(message)             # accessible here

greet()
# Output: Hello, World!

print(message)  # NameError: name 'message' is not defined

Почему локальная область видимости важна

Локальная область видимости позволяет использовать простые, описательные имена, такие как total, result или i, внутри каждой функции, не допуская конфликтов ни между ними, ни с кодом на уровне модуля.

def calculate_area(radius):
    pi = 3.14159        # local to this function
    area = pi * radius ** 2
    return area

def calculate_volume(radius, height):
    pi = 3.14159        # completely separate local 'pi'
    volume = pi * radius ** 2 * height
    return volume

print(calculate_area(5))       # 78.53975
print(calculate_volume(5, 10)) # 785.3975

Обе функции используют pi независимо. Никакого конфликта нет.

Вложенная область видимости

Когда функция определена внутри другой функции, внутренняя функция может читать имена из внешней (охватывающей) функции. Это и есть E в LEGB.

def outer():
    color = "blue"      # enclosing variable

    def inner():
        print(color)    # reads from enclosing scope

    inner()

outer()
# Output: blue

Внутренняя функция может читать color без каких-либо специальных ключевых слов, поскольку Python автоматически поднимается к охватывающей области видимости.

Изменение переменной во вложенной области видимости с помощью nonlocal

Чтение переменной из охватывающей области происходит автоматически, но присвоение ей требует ключевого слова nonlocal. Без него Python расценивает присвоение как создание новой локальной переменной, а не изменение охватывающей.

def make_counter():
    count = 0           # enclosing variable

    def increment():
        nonlocal count  # declare intent to modify the enclosing 'count'
        count += 1
        return count

    return increment

counter = make_counter()
print(counter())  # 1
print(counter())  # 2
print(counter())  # 3

Каждый вызов counter() изменяет одну и ту же переменную count. Этот паттерн лежит в основе замыканий — подробнее см. Python Closures.

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

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

language = "Python"     # global variable

def display_language():
    print(language)     # reads global without any keyword

display_language()
# Output: Python

Изменение глобальной переменной с помощью global

Читать глобальную переменную из функции можно без каких-либо ключевых слов. Но если вы хотите присвоить ей значение, сначала необходимо объявить её с помощью global:

total = 0               # global variable

def add_to_total(n):
    global total        # declare intent to modify the global
    total += n

add_to_total(5)
add_to_total(3)
print(total)            # 8

Без global total строка total += n выбросит UnboundLocalError, потому что Python будет считать total локальной переменной, которой ещё не было присвоено значение.

Подробнее о глобальных переменных см. Python Global Variables.

Когда следует избегать global

Активное использование global усложняет тестирование кода и понимание его логики. Предпочтительнее возвращать значения из функций и передавать данные в виде аргументов. Используйте global только для подлинного состояния уровня модуля — флагов конфигурации, счётчиков или кешей — и делайте это редко.

Встроенная область видимости

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

python— editable, runs on the server

Распространённые встроенные имена: print, len, range, type, int, str, list, dict, set, tuple, open, input, max, min, sum, sorted, enumerate, zip и map.

Не затеняйте встроенные имена

Поскольку встроенная область видимости проверяется последней, любое локальное или глобальное имя с таким же написанием будет её затенять. Это распространённая ошибка:

# Bad: shadows the built-in 'list'
list = [1, 2, 3]
print(type(list))   # <class 'list'> — still works here

new = list([4, 5])  # TypeError: 'list' object is not callable

Удалите затеняющее имя, чтобы восстановить доступ к встроенному:

del list            # remove the local/global shadowing name
new = list([4, 5])  # works again: [4, 5]

Встроенный модуль доступен как builtins, если когда-либо потребуется обратиться к нему явно:

import builtins
print(builtins.len([1, 2, 3]))  # 3

Распространённые ошибки

UnboundLocalError

Самая частая ошибка, связанная с областью видимости в Python, — это чтение имени до его присвоения внутри функции, когда в той же функции есть присвоение этому имени:

x = 10

def bad_func():
    print(x)   # UnboundLocalError! Python sees x = 20 below
    x = 20     # this makes 'x' local for the whole function

bad_func()

Python во время компиляции определяет, что x является локальной переменной (поскольку ей присваивается значение в функции). Попытка прочитать её до присвоения вызывает UnboundLocalError: local variable 'x' referenced before assignment.

Исправить это можно, объявив global x либо не присваивая значение x внутри функции.

Затенение переменных

Локальная переменная с тем же именем, что и глобальная, неявно затеняет глобальную. Обычно это делается намеренно, но это может вызывать трудноуловимые ошибки, когда вы ожидаете читать глобальную переменную:

x = 10          # global

def my_func():
    x = 20      # local — shadows the global
    print(x)    # 20, not 10

my_func()
print(x)        # 10 — global unchanged

Проверка области видимости во время выполнения

Python предоставляет содержимое текущей области видимости через две встроенные функции.

locals() возвращает словарь текущей локальной области видимости (или пространство имён уровня модуля, если вызвана на верхнем уровне):

def show_locals():
    a = 1
    b = "hello"
    print(locals())   # {'a': 1, 'b': 'hello'}

show_locals()

globals() возвращает словарь глобального (уровня модуля) пространства имён:

language = "Python"
print("language" in globals())  # True

Эти функции полезны для отладки и интроспекции, но не следует использовать их для динамического управления переменными в продакшн-коде.

Область видимости и функции

Функции в Python являются объектами и сами по себе представляют собой имена, живущие в некоторой области видимости. Функция, определённая на верхнем уровне модуля, является глобальной; функция, определённая внутри другой функции, является локальной для охватывающей функции.

def outer():
    def helper():       # helper is local to outer
        return 42
    return helper()

print(outer())          # 42
# helper()              # NameError: helper is not defined here

О том, как определяются функции, см. Python Functions, а об анонимных функциях, которые также подчиняются правилу LEGB, — Python Lambda.

Краткий справочник

Ключевое словоДействие
(нет)Чтение из ближайшей охватывающей области по правилу LEGB
global xУказывает текущей функции, что x ссылается на имя уровня модуля
nonlocal xУказывает текущей функции, что x ссылается на имя в ближайшей охватывающей функции

Практика

Практика
In Python, what are the four types of scopes in the order that they are checked?
In Python, what are the four types of scopes in the order that they are checked?
Was this page helpful?