Область видимости определяет видимость имени переменной в блоке кода. Определение переменной в коде происходит в результате операций связывания или присваивания.
Если переменная определена в блоке кода, ее область действия включает этот блок. Если определение встречается в функциональном блоке, область действия расширяется на любые блоки кода, входящие в этот блок, если только содержащий блок не вводит другую привязку для имени (nonlocal
или global
).
Если переменная используется в блоке кода, то имя переменной разрешается с использованием ближайшей заключающей ее области. Набор всех таких областей, видимых для блока кода, называется средой блока environment
.
Если имя переменной не найдено вообще, возникает исключение NameError
. Если текущая область является областью определения функции, а имя ссылается на локальную переменную, которая еще не была привязана к значению, то возникает исключение UnboundLocalError
. UnboundLocalError
- это подкласс NameError
.
Если определение переменной происходит где-либо в блоке кода, все случаи использования имени в блоке рассматриваются как ссылки на текущий блок. Это может привести к ошибкам, когда имя используется внутри блока до его привязки. Это правило неуловимо. В Python отсутствует объявления переменных и разрешены операций связывания и присваивания имен переменных в любом месте блока кода. Локальные переменные блока кода могут быть определены путем сканирования всего текста этого блока на предмет операций связывания и присваивания имен.
Пространство имен для модуля создается автоматически при первом импорте import
модуля. Основной модуль для скрипта всегда называется __main__
.
global
и nonlocal
.Если оператор global
встречается внутри блока, все случаи использования имени переменной, указанной в этом операторе, относятся к связыванию этого имени в пространстве имен верхнего уровня. Имена разрешаются в пространстве имен верхнего уровня путем поиска глобального пространства имен, т. е. пространства имен файла сценария (модуля) содержащего код и пространства имен встроенных модулей builtins
. Сначала выполняется поиск в глобальном пространстве имен. Если имя не найдено, выполняется поиск в пространстве имен встроенных модулей builtins
. Инструкция global
должна предшествовать всем видам использования имени переменной в блоке кода.
Инструкция global
имеет ту же область действия, что и операция связывания имени в том же блоке. Если ближайшая заключающая область для свободной переменной содержит оператор global
, свободная переменная рассматривается как глобальная. Свободные переменные разрешаются не в ближайшем окружающем пространстве имен, а в глобальном пространстве имен.
Инструкция nonlocal
заставляет соответствующее имя ссылаться на ранее связанные переменные в ближайшей области действия заключающей функции. Во время компиляции будет вызываться исключение SyntaxError
, если данное имя не существует ни в одной области действия заключающей функции.
x = 10 def gglobal(): global x x = 20 def outer(): y = 5 def enclosing(): nonlocal y y = 15 enclosing() print(f'{y=}') gglobal() outer() print(f'{x=}') # ВЫВОД скрипта: # y=15 (изменена в `enclosing()`) # x=20 (изменена в `gglobal()`)
Ключевое слово global
сообщает Python, что имеется в виду global x
, а nonlocal
указывает, что ориентируемся на y
из охватывающей функции.
Блоки определения классов и аргументы для exec()
и eval()
являются особыми в контексте разрешения имен. Определение класса - это исполняемый оператор, который может использовать и присваивать имена. Эти ссылки следуют обычным правилам разрешения имен, за исключением того, что несвязанные локальные переменные ищутся в глобальном пространстве имен. Пространство имен определения класса становится словарем атрибутов класса. Область видимости имен, определенных в блоке класса, ограничена блоком этого класса. Область видимости класса не распространяется на блоки методов, к которым относятся короткие выражения для создания списков, кортежей, словарей и множеств, а так же выражения-генераторы, поскольку они реализуются с использованием области действия функции. Это означает, что следующее не удастся:
class A: a = 42 b = list(a + i for i in range(10))
Дополнительно смотрите материал "Пространство имен и область видимости в классах"
Python имеет различные пространства имен, создаваемые и удаляемые в разное время:
global
) : специфичное для модуля или скрипта. Создается при импорте модуля или запуске скрипта.local
): создается при вызове функции. Как только выполнение функции завершается, пространство имен отбрасывается.Область действия определяет область кода, в которой к переменной можно получить доступ или изменить ее. В Python есть четыре основных области действия переменных:
Эти области образуют правило LEGB, которому Python следует при разрешении имен переменных.
Типы пространств имен
x = 10 # global variable def outer(): y = 5 # enclosing variable def inner(): z = 3 # local var print(x, y, z) inner() outer()
Когда вызывается функция inner()
, то она обращается к:
z
из его локальной области видимости.y
из охватывающей области outer_function()
.x
из глобальной области видимости.Если локальная переменная имеет то же имя, что и глобальная переменная или встроенная, она затеняет глобальную или встроенную переменную:
x = 10 def shadow(): x = 5 print(x) shadow() # 5 print(x) # 10 (глобальная переменная `x` не изменилась)
Затенение может привести к неожиданному поведению, поэтому рекомендуется избегать использования одних и тех же имен в разных областях.