Пространство имен и область видимости Python3
Пространство имён
Сначала рассмотрим отрывок из официальной документации:
Пространство имён — это сопоставление имён объектам.Большинство пространств имён в настоящее время реализованы как словари Python.
Пространство имён — это сопоставление имён объектам. Большинство пространств имён в настоящее время реализованы как словари Python.
Пространства имён позволяют избежать конфликтов имён в проектах. Каждое пространство имён независимо и не связано с другими, поэтому в одном пространстве имён не может быть одинаковых имён, но в разных пространствах имён могут быть одинаковые имена без каких-либо последствий.
Приведём пример из компьютерной системы: папка (каталог) может содержать несколько папок, и в каждой папке не может быть файлов с одинаковыми именами, но файлы в разных папках могут иметь одинаковые имена.

Обычно существует три типа пространств имён:
- Встроенные имена (встроенные имена), имена, встроенные в язык Python, например имена функций abs, char и имена исключений BaseException, Exception и т. д.
- Глобальные имена (глобальные имена), имена, определённые в модуле, хранящие переменные модуля, включая функции, классы, другие импортированные модули, а также переменные и константы уровня модуля.
- Локальные имена (локальные имена), имена, определённые в функции, хранящие переменные функции, включая параметры функции и локально определённые переменные. (Определённые в классе также включаются.)

Порядок поиска в пространствах имён:
Предположим, мы хотим использовать переменную example, тогда порядок поиска в Python таков:Локальное пространство имён -> Глобальное пространство имён -> Встроенное пространство имён。
Если переменная example не найдена, поиск прекращается и возбуждается исключение NameError:
NameError: name 'example' is not defined.
Жизненный цикл пространства имён:
Жизненный цикл пространства имён зависит от области видимости объекта. Если объект завершил выполнение, жизненный цикл этого пространства имён заканчивается.
Следовательно, мы не можем получить доступ к объектам во внутреннем пространстве имён из внешнего пространства имён.
Пример
var1 = 5
def some_func():
# var2 — локальное имя
var2 = 6
def some_inner_func():
# var3 — это вложенное локальное имя
var3 = 7
Как показано на рисунке ниже, одно и то же имя объекта может существовать в нескольких пространствах имён.

Область действия
Область видимости — это текстовая область программы Python, в которой пространство имён доступно напрямую. «Доступно напрямую» здесь означает, что неквалифицированная ссылка на имя пытается найти это имя в пространстве имён.
Область видимости — это текстовая область программы Python, в которой пространство имён доступно напрямую.
В программе Python прямой доступ к переменной будет обращаться ко всем областям видимости от внутренней к внешней, пока она не будет найдена; в противном случае будет сообщено об ошибке неопределённого имени.
В Python к переменным программы нельзя обратиться из любого места; разрешения на доступ зависят от того, где переменной присвоено значение.
Область видимости переменной определяет, какая часть программы может обращаться к конкретному имени переменной.
В Python всего 4 области видимости, а именно:
Существует четыре области видимости:
- L(Local): Самый внутренний уровень, содержащий локальные переменные, например внутри функции/метода.
- E(Enclosing): Содержит переменные, которые являются нелокальными (non-local) и в то же время не глобальными (non-global). Например, при двух вложенных функциях, если функция (или класс) A содержит другую функцию B, то для имён в B область видимости в A является нелокальной.
- G(Global): Самый внешний уровень текущего скрипта, например глобальные переменные текущего модуля.
- B(Built-in): Содержит встроенные переменные/ключевые слова и т. д., поиск по ним выполняется последним.
Правило LEGB (Local, Enclosing, Global, Built-in): Порядок, в котором Python ищет переменные, таков:L –> E –> G –> B。
- Local: Локальная область видимости текущей функции.
- Enclosing: Область видимости внешней функции, содержащей текущую функцию (если есть вложенные функции).
- Global: Глобальная область видимости текущего модуля.
- Built-in: Встроенная область видимости Python.
Если не найдено локально, поиск продолжится во вмещающей локальной области видимости (например, замыкания); если всё ещё не найдено, он будет искать в глобальной области видимости, а затем во встроенной области видимости.

g_count = 0 # 全局作用域
def outer():
o_count = 1 # 闭包函数外的函数中
def inner():
i_count = 2 # 局部作用域
Встроенная область видимости реализована через стандартный модуль с именем builtin, но само имя переменной не помещается во встроенную область видимости, поэтому необходимо импортировать этот файл, чтобы использовать его. В Python 3.0 можно использовать следующий код, чтобы точно увидеть, какие переменные предопределены:
>>> import builtins >>> dir(builtins)
В Python только модули, классы и функции (def, lambda) создают новые области видимости. Другие блоки кода (такие как if/elif/else, try/except, for/while и т. д.) не создают новые области видимости. То есть переменные, определённые внутри этих инструкций, также могут быть доступны извне, как в следующем коде:
>>> if True: ... msg = 'I am from Example' ... >>> msg 'I am from Example' >>>
В примере переменная msg определена в блоке оператора if, но к ней всё ещё можно получить доступ извне.
Если msg определена внутри функции, то это локальная переменная, и к ней нельзя получить доступ извне:
>>> def test(): ... msg_inner = 'I am from Example' ... >>> msg_inner Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'msg_inner' is not defined >>>
Из сообщения об ошибке видно, что msg_inner не определена и не может использоваться, потому что это локальная переменная, и её можно использовать только внутри функции.
Глобальные и локальные переменные
Переменные, определённые внутри функции, имеют локальную область видимости, а определённые вне функции — глобальную область видимости.
К локальным переменным можно получить доступ только внутри функции, где они объявлены, тогда как к глобальным переменным можно получить доступ во всей программе.
Переменные, объявленные внутри функции, действительны только в области видимости внутри функции. При вызове функции эти внутренние переменные добавляются во внутреннюю область видимости функции и не влияют на переменные с тем же именем вне функции, как в следующем примере:
Пример (Python 3.0+)
Вывод приведенного выше примера:
函数内是局部变量 : 30 函数外是全局变量 : 0
1. Глобальные переменные: Переменные, определённые вне функции, доступны во всём файле. Переменные, определённые вне функции, видимы всем функциям, если только внутри функции не определена локальная переменная с тем же именем.
Пример
def my_function():
print(x) # Можно получить доступ к глобальной переменной x
my_function() # Выводит 10
2. Локальные переменные: Переменные, определённые внутри функции, действительны только внутри функции, и к ним нельзя получить доступ извне. Локальные переменные имеют более высокий приоритет, чем глобальные переменные, поэтому если локальная переменная и глобальная переменная имеют одинаковое имя, внутри функции используется локальная переменная.
Пример
x = 5 # Локальная переменная
print(x) # Доступ к локальной переменной x
my_function() # Выводит 5
print(x) # Ошибка: NameError: name 'x' is not defined
Ключевые слова global и nonlocal
Когда внутренняя область видимости хочет изменить переменную во внешней области видимости, нужны ключевые слова global и nonlocal.
В следующем примере изменяется глобальная переменная num:
Пример (Python 3.0+)
Вывод приведенного выше примера:
1 123 123
Если вы хотите изменить переменную во вложенной области видимости (охватывающей области видимости, внешней неглобальной области), вам нужно ключевое слово nonlocal, как в следующем примере:
Пример (Python 3.0+)
Вывод приведенного выше примера:
100 100
Существует также особый случай. Предположим, выполняется следующий код:
Пример (Python 3.0+)
Когда выполняется вышеуказанная программа, сообщение об ошибке выглядит так:
Traceback (most recent call last):
File "test.py", line 7, in <module>
test()
File "test.py", line 5, in test
a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment
Сообщение об ошибке — это ошибка ссылки на локальную область видимости, потому что a в функции test использует локальную переменную, которая не определена и не может быть изменена.
Измените a на глобальную переменную:
Пример
Результат выполнения:
Это также можно передать через параметры функции:
Пример (Python 3.0+)
Результат выполнения:
Итог
- Глобальные переменныеОпределены вне функции, доступны во всём файле.
- Локальные переменныеОпределены внутри функции, доступны только внутри функции.
- Используйте
globalВы можете изменять глобальные переменные внутри функции. - Используйте
nonlocalВы можете изменять переменные внешней функции внутри вложенных функций.