Найти в Дзене

Обучение Python ч.8.Область видимости переменных

Область видимости переменной — это конкретный блок кода, в котором мы можем получить доступ к некоторой переменной. Это та «площадь» кода, в которой мы можем «увидеть» некоторую переменную и произвести над ней те или иные действия, например, получить её значение, удалить или изменить. Существует три контекста области видимости: Глобальная
Локальная
Нелокальная Глобальная область видимости Глобальная область видимости — это область видимости переменной, при которой переменная объявлена как бы в самом верху иерархии и «видна» всем блокам кода, например: car_name = "Tesla Model X" def start():
print(car_name + " начала движение!") def stop(): print(car_name + " прекратила движение!") start()
stop() Выведет: Tesla Model X начала движение!
Tesla Model X прекратила движение! Несложно догадаться, что переменная объявленная вне контекста конкретной функции, объявленная как бы «выше» этих функций является глобальной, то есть доступна для всех остальных функций. Глобальную переме
Оглавление

Область видимости переменной — это конкретный блок кода, в котором мы можем получить доступ к некоторой переменной. Это та «площадь» кода, в которой мы можем «увидеть» некоторую переменную и произвести над ней те или иные действия, например, получить её значение, удалить или изменить.

Существует три контекста области видимости:

Глобальная
Локальная
Нелокальная

Глобальная область видимости

Глобальная область видимости — это область видимости переменной, при которой переменная объявлена как бы в самом верху иерархии и «видна» всем блокам кода, например:

car_name = "Tesla Model X"

def start():
print(car_name + " начала движение!")

def stop():

print(car_name + " прекратила движение!")

start()
stop()

Выведет:

Tesla Model X начала движение!
Tesla Model X прекратила движение!

Несложно догадаться, что переменная объявленная вне контекста конкретной функции, объявленная как бы «выше» этих функций является глобальной, то есть доступна для всех остальных функций.

Глобальную переменную также можно объявить и внутри функции, при помощи ключевого слова global:

def start():
global car_name
car_name = "Tesla Model X"
print(car_name + " начала движение!")

def stop():
print(car_name + " прекратила движение!")

start()
stop()

Выведет:

Tesla Model X начала движение!
Tesla Model X прекратила движение!

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

Локальная область видимости – это область видимости ограниченная некоторым блоком кода, к этой переменной можно получить только в том блоке кода, в котором она была объявлена. Обращение к локальной переменной за пределами её области видимости вызовет ошибку, т.к. данной переменной там не существует:

def start():
car_name = "Tesla Model X" # Это локальная переменная
print(car_name + " начала движение!")

def stop():
print(car_name + " прекратила движение!")

start() # Tesla Model X начала движение!
stop() # Ошибка: NameError: name 'car_name' is not defined

В данном случае, переменная car_name была определена внутри функции start и существовала только в этой функции. Область видимости переменной car_name является функция start, поэтому попытка получить значение этой переменной в функции stop привело к ошибке, т.к. в этой функции переменная с именем car_name не была объявлена.

Конфликт локальной и глобальной области видимости

Рассмотрим пример:

car_name = "BMW"

def start():
car_name = "Tesla Model X"
print(car_name + " начала движение!")

def stop():
print(car_name + " прекратила движение!")

start()
stop()

Подумайте, что выведет функция start, а что, функция stop. С одной стороны, кажется очевидным, что мы определили глобальную переменную и задали ей значение BMW, затем в функции start мы изменили значение глобальной переменной car_name на Tesla Model X и теперь при вызове функций start и stop мы получим вывод именно модели Tesla Model X:

Tesla Model X начала движение!
Tesla Model X прекратила движение!
Давайте запустим данный код и посмотрим, что он выведет на самом деле: Tesla Model X начала движение!
BMW прекратила движение!

Но почему так? Всё просто, в функции start мы присвоили значение Tesla Model X не для глобальной переменной, нет, мы создали новую локальную переменную с тем же именем и присвоили ей значение. Таким образом работает конфликт областей видимости в Python. Если в локальной области видимости, например, в функции определяется переменная с таким же именем, что и у глобальной переменной, то в контексте этой области видимости значение глобальной переменной будет перезаписано локальным значением.
Но при этом вне локальной области видимости значение глобальной переменной останется неизменным, как бы оно не перезаписывалось в локальной области видимости.
Чтобы изменить значение глобальной переменной в локальной области видимости, нужно её также «глобализовать» при помощи ключевого слова global.

Нелокальная область видимости

В Python также есть возможность создавать вложенные функции. У этих вложенных функций также существует локальная область видимости и иногда возникает проблема при передаче значения переменной, объявленной в одной из вложенных функций, например:

def car():
# Счётчик количества поездок
trip = 0
def start():
trip += 1
car_name = "Tesla Model X"
print(car_name + " начала движение!")
print("Номер поездки: " + str(trip))

return start
car = car()
car()
car()
car()
car()

Выведет:

UnboundLocalError: local variable 'trip' referenced before assignment

Дело в том, что переменная trip к которой мы обращаемся во вложенной функции start – не объявлена в этой функции, она объявлена выше, в функции car и поэтому мы прибавляем единицу к несуществующей в данном контексте переменной.
Ведь переменная trip не является глобальной. Чтобы решить эту проблему, нам нужно как бы принять локальную переменную trip из функции car в функцию start, для этого используют ключевое слово nonlocal:

def car():
# Счётчик количества поездок
trip = 0
def start():
nonlocal trip
trip += 1
car_name = "Tesla Model X"
print(car_name + " начала движение!")
print("Номер поездки: " + str(trip))

return start
car = car()
car()
car()
car()
car()

Выведет:

Tesla Model X начала движение!
Номер поездки: 1
Tesla Model X начала движение!
Номер поездки: 2
Tesla Model X начала движение!
Номер поездки: 3
Tesla Model X начала движение!
Номер поездки: 4

Внутри функции, область видимости которой не относится к области видимости заданной переменной мы объявили переменную trip нелокальной и теперь у нас появился локальный доступ, за пределами локальной области видимости данной переменной.
Это достаточно сложная концепция и в данном случае она вам, скорее всего не пригодится. Поэтому советую лишь поверхностно с ней ознакомиться и в последствии вернуться лишь тогда, когда вам в действительности понадобится работать с нелокальной областью видимости.
Для прохождения дальнейших уроков и практических заданий в курсе, эти знания вам не пригодятся.

Следующий урок