Пространство имен и область видимости Python3

Пространство имён

Сначала рассмотрим отрывок из официальной документации:

Пространство имён — это сопоставление имён объектам.Большинство пространств имён в настоящее время реализованы как словари Python.

Пространство имён — это сопоставление имён объектам. Большинство пространств имён в настоящее время реализованы как словари Python.

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

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

Обычно существует три типа пространств имён:

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

Порядок поиска в пространствах имён:

Предположим, мы хотим использовать переменную example, тогда порядок поиска в Python таков:Локальное пространство имён -> Глобальное пространство имён -> Встроенное пространство имён。

Если переменная example не найдена, поиск прекращается и возбуждается исключение NameError:

NameError: name 'example' is not defined.

Жизненный цикл пространства имён:

Жизненный цикл пространства имён зависит от области видимости объекта. Если объект завершил выполнение, жизненный цикл этого пространства имён заканчивается.

Следовательно, мы не можем получить доступ к объектам во внутреннем пространстве имён из внешнего пространства имён.

Пример

# var1 — глобальное имя
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。

  1. Local: Локальная область видимости текущей функции.
  2. Enclosing: Область видимости внешней функции, содержащей текущую функцию (если есть вложенные функции).
  3. Global: Глобальная область видимости текущего модуля.
  4. 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+)

#!/usr/bin/python3 total = 0 # Это глобальная переменная # Описание функции def sum( arg1, arg2 ): # Возвращает сумму двух параметров. total = arg1 + arg2 # здесь total — локальная переменная. print ("Внутри функции это локальная переменная:", total) return total # Вызов функции sum sum( 10, 20 ) print ("Вне функции это глобальная переменная:", total)

Вывод приведенного выше примера:

函数内是局部变量 :  30
函数外是全局变量 :  0

1. Глобальные переменные: Переменные, определённые вне функции, доступны во всём файле. Переменные, определённые вне функции, видимы всем функциям, если только внутри функции не определена локальная переменная с тем же именем.

Пример

x = 10  # Глобальная переменная

def my_function():
    print(x)  # Можно получить доступ к глобальной переменной x

my_function()  # Выводит 10

2. Локальные переменные: Переменные, определённые внутри функции, действительны только внутри функции, и к ним нельзя получить доступ извне. Локальные переменные имеют более высокий приоритет, чем глобальные переменные, поэтому если локальная переменная и глобальная переменная имеют одинаковое имя, внутри функции используется локальная переменная.

Пример

def my_function():
    x = 5  # Локальная переменная
    print(x)  # Доступ к локальной переменной x

my_function()  # Выводит 5
print(x)  # Ошибка: NameError: name 'x' is not defined

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

Когда внутренняя область видимости хочет изменить переменную во внешней области видимости, нужны ключевые слова global и nonlocal.

В следующем примере изменяется глобальная переменная num:

Пример (Python 3.0+)

#!/usr/bin/python3 num = 1 def fun1(): global num # Нужно объявить с помощью ключевого слова global print(num) num = 123 print(num) fun1() print(num)

Вывод приведенного выше примера:

1
123
123

Если вы хотите изменить переменную во вложенной области видимости (охватывающей области видимости, внешней неглобальной области), вам нужно ключевое слово nonlocal, как в следующем примере:

Пример (Python 3.0+)

#!/usr/bin/python3 def outer(): num = 10 def inner(): nonlocal num # Объявить с помощью ключевого слова nonlocal num = 100 print(num) inner() print(num) outer()

Вывод приведенного выше примера:

100
100

Существует также особый случай. Предположим, выполняется следующий код:

Пример (Python 3.0+)

#!/usr/bin/python3 a = 10 def test(): a = a + 1 print(a) test()

Когда выполняется вышеуказанная программа, сообщение об ошибке выглядит так:

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 на глобальную переменную:

Пример

#!/usr/bin/python3 a = 10 def test(): global a a = a + 1 print(a) test()

Результат выполнения:

11

Это также можно передать через параметры функции:

Пример (Python 3.0+)

#!/usr/bin/python3 a = 10 def test(a): a = a + 1 print(a) test(a)

Результат выполнения:

11

Итог

  • Глобальные переменныеОпределены вне функции, доступны во всём файле.
  • Локальные переменныеОпределены внутри функции, доступны только внутри функции.
  • ИспользуйтеglobalВы можете изменять глобальные переменные внутри функции.
  • ИспользуйтеnonlocalВы можете изменять переменные внешней функции внутри вложенных функций.
Другие расширения