Области видимости переменных и пространства имен в Python

В этом уроке вы узнаете, как работают области видимости переменных в Python. После изучения руководства у вас будет четкое представление о встроенных, локальных и глобальных областях видимости.

Содержание

Что такое области видимости переменных в Python?

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

Имя переменной и ее привязка (имя и объект) существуют только в определенных частях вашего кода. Часть кода, в которой вы определяете имя/привязку, называется лексической областью действия переменных.

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

Глобальные области

Глобальная область видимости — это, по сути, область видимости модуля. Глобальная область действия охватывает только один файл исходного кода Python. Python не имеет по-настоящему глобальной области видимости, охватывающей все модули, за исключением встроенной области.

Встроенная область — это специальная область, которая предоставляет глобально доступные объекты, такие как print, len, None, True и False. По сути, встроенные и глобальные переменные существуют повсюду внутри модуля.

Внутренне глобальные области вложены во встроенную область:

Области переменных в Python

Если вы получаете доступ к переменной из области, а Python не находит ее в пространстве имен этой области, он будет искать в пространстве имен охватывающей области.

Предположим, что у вас есть следующий оператор в модуле app.py:

print('Hello')

В этом модуле app.py Python ищет функцию print в области модуля(app.py).

Поскольку Python не находит определение функции print в области модуля app.py, Python обращается к охватывающей области, которая является встроенной областью, и ищет там данную функцию. В этом случае он может найти функцию print во встроенной области.

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

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

print(counter)

В этом примере Python не находит counter в текущей глобальной области видимости. Поэтому Python ищет его во внешней области, которая является встроенной.

Однако счетчик переменных не существует во встроенной области. Поэтому Python выдает исключение NameError:

NameError: name 'counter' is not defined

Локальные области

При создании функции вы можете определить параметры и переменные для функции. Например:

def increment(counter, by=1):
    result = counter + by
    return result

Когда вы выполняете код, Python выполняет две фазы: компиляцию и выполнение.

Когда Python компилирует файл, он добавляет функцию increment() в глобальную область видимости. Кроме того, Python определяет, что переменные counter, by и result внутри функции increment() будут локальными для функции increment(). И Python не будет создавать переменные counter, by и result до тех пор, пока функция не будет выполнена.

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

В нашем примере, когда вы вызываете функцию increment():

increment(10,2)

… Python создает локальную область видимости для вызова функции increment().

Кроме того, Python создает локальные переменные counter, by и result в локальном пространстве имен и привязывает их к значениям 10, 2 и 12.

Когда функция завершится, Python удалит локальную область. И все локальные переменные, такие как переменные counter, by и result, выходят за рамки. Если вы попытаетесь получить доступ к этим переменным снаружи функции increment(), вы получите сообщение об ошибке.

И если вы снова вызовете функцию increment():

increment(100,3)

… Python создает новую локальную область видимости и переменные, включая counter, by и result, и привязывает их к значениям 100, 3 и 103.

Поиск переменных

В Python области видимости являются вложенными. Например, локальные области вложены в область модуля. Области модулей вложены во встроенную область видимости:

Поиск объектов в областях видимости Python

Когда вы получаете доступ к объекту, привязанному к переменной, Python пытается найти объект:

  • сначала в текущей локальной области
  • затем переходит вверх по цепочке охватывающих областей, если не находит объект в текущей области.

Ключевое слово global

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

counter = 10


def current():
    print(counter)


current()

В этом примере, когда функция current() выполняется, Python ищет переменную counter в локальной области.

Поскольку Python не находит ее, он ищет переменную в глобальной области видимости. В этом случае Python может найти переменную-счетчик в глобальной области видимости.

Однако если вы присвоите значение глобальной переменной изнутри функции, Python вместо этого поместит эту переменную в локальное пространство имен. Например:

counter = 10


def reset():
    counter = 0
    print(counter)


reset()
print(counter)

Выход:

0 
10

Во время компиляции Python интерпретирует counter как локальную переменную.

Когда функция reset() запущена, Python находит счетчик в локальной области. Оператор print(counter) внутри функции reset() показывает значение counter, равное нулю. Когда мы печатаем counter после завершения функции reset(), вместо этого он показывает 10.

В этом примере локальная переменная counter маскирует глобальную переменную counter. Если вы хотите получить доступ к глобальной переменной изнутри функции, вы можете использовать ключевое слово global.

Например:

counter = 10


def reset():
    global counter
    counter = 0
    print(counter) # 0


reset()

print(counter) # 0

Выход:

0
0

В этом примере следующее утверждение:

global counter

… сообщает Python, что переменная counter привязана к глобальной, а не локальной области.

Обратите внимание: не рекомендуется обращаться к глобальной переменной внутри функции.

Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *