Пространство имен и область видимости в Python
Последняя строка «Дзен Питона» гласит: «Пространства имен — отличная штука! Давайте будем использовать ее чаще!» . Что же это за загадочные пространства имен? Давайте сначала узнаем, что такое имя.
Примечание. Если не читали «Дзен Питона», введите import this в интерпретаторе.
Например, когда мы присваиваем a = 2 , 2 — это объект, хранящийся в памяти, а a — это имя, с которым мы его связываем. Мы можем получить адрес объекта в ОЗУ с помощью встроенной функции id () . Давайте посмотрим, как ей пользоваться. Имя (оно же идентификатор) — это просто название, данное объекту. В Python всё — объекты, а имя — это способ доступа к объекту.
# Примечание: вы можете получить другие значения id. a = 2 print('id(2) =', id(2)) print('id(a) =', id(a))
Здесь оба аргумента ссылаются на 2 , поэтому у них одинаковый id. Давайте сделаем задачу немного интереснее.
# Примечание: вы можете получить другие значения id. a = 2 print('id(a) =', id(a)) a = a+1 print('id(a) =', id(a)) print('id(3) =', id(3)) b = 2 print('id(b) =', id(b)) print('id(2) =', id(2))
id(a) = 9302208
id(a) = 9302240
id(3) = 9302240
id(b) = 9302208
id(2) = 9302208
Что происходит в программе выше? Давайте рассмотрим это на диаграмме:
Сначала создается объект 2 и с ним связывается имя a . Когда мы обновляем значение a = a + 1 , создается новый объект 3 , и теперь уже a ссылается на этот объект.
Обратите внимание, что id (a) и id (3) выдают одинаковые значения.
Кроме того, когда выполняется строка b = 2 , новое имя b связывается с предыдущим объектом 2 .
Это эффективное решение, поскольку Python не нужно создавать дубликаты объектов. Такая динамическая привязка имен и делает Python мощным. Также имя может относиться к любому типу объекта.
>>> a = 5 >>> a = 'Привет, мир!' >>> a = [1,2,3]
Все эти привязки действительны, и a будет ссылаться на три различных типа объектов на разных стадиях. Функции тоже являются объектами, поэтому имя может ссылаться и на них.
def printHello(): print("Привет!") a = printHello a()
Как видите, имя a может ссылаться на функцию и мы можем вызывать ее, используя это имя.
Что такое пространство имен
Теперь, когда мы понимаем, что такое имена, мы можем перейти к понятию пространства имен.
Проще говоря, пространство имен — это набор имен.
В Python вы можете представить себе пространство имен в виде отображения каждого имени, которое вы определили, на соответствующие объекты.
В определенный момент времени могут сосуществовать несколько пространств имен, и все они будут полностью изолированы.
Пространство имен, содержащее все встроенные имена, создается при запуске интерпретатора Python и существует, пока интерпретатор не завершит работу.
По этой причине встроенные функции, такие как id () , print () и т. д., всегда доступны из любой части программы.
Каждый модуль создает свое собственное глобальное пространство имен.
Все разные пространства имен изолированы. Следовательно, одно и то же имя, которое используется в разных модулях, не вызывает противоречий.
В модулях могут быть различные функции и классы. При вызове функции создается локальное пространство имен данной функции. Так же — с классом. Следующая диаграмма поможет лучше понять эту концепцию.
Область видимости переменных
Несмотря на то, что различные пространства имен могут быть определены одновременно, мы не сможем получить доступ ко всем из них в каждой части программы. Тут в игру вступает область видимости.
Область видимости — это часть программы, из которой можно получить доступ к пространству имен напрямую, без какого-либо префикса.
В любой момент работы программы существует как минимум три области видимости:
- область видимости текущей функции, имеющей локальные имена;
- область видимости модуля, имеющего глобальные имена;
- самая внешняя область видимости, хранящая встроенные имена.
Когда объект вызывается внутри функции, Python сначала ищет имя в локальном пространстве имен, затем в глобальном пространстве имен и, наконец, во встроенном пространстве имен.
Если внутри одной функции определена другая, то пространство имен последней будет вложено в локальное пространство первой.
Пример работы области видимости и пространства имен
def outer_function(): b = 20 def inner_function(): c = 30 a = 10
Здесь переменная a находится в глобальном пространстве имен. Переменная b находится в локальном пространстве имен outer_function () , а c находится во вложенном локальном пространстве имен inner_function () .
Когда мы находимся в inner_function () , c является для нас локальной переменной, b нелокальной, а a — глобальной. Мы можем получить доступ к значениям всех трех переменных a , b и c , однако изменять значение мы можем только у c .
Если мы попытаемся изменить значение b , в локальном пространстве имен будет создана новая переменная b , которая отличается от нелокальной версии b . То же самое происходит, когда мы изменяем значение a .
Однако, если мы объявим a как глобальную, все обращения будут направлены к глобальной a . Точно так же, если мы хотим поменять значение переменной b , она должна быть объявлена нелокальной. Следующий пример демонстрирует это.
def outer_function(): a = 20 def inner_function(): a = 30 print('a = ', a) inner_function() print('a = ', a) a = 10 outer_function() print('a = ', a)
В этой программе три разные переменные a определены в отдельных пространствах имен. А в следующей программе не так.
def outer_function(): global a a = 20 def inner_function(): global a a = 30 print('a = ', a) inner_function() print('a = ', a) a = 10 outer_function() print('a = ', a)
Здесь все обращения и объявления относятся к глобальной переменной a благодаря ключевому слову global.
СodeСhick.io — простой и эффективный способ изучения программирования.
2023 © ООО «Алгоритмы и практика»