JavaRush /Курсы /Модуль 1: Python Core /Области видимости переменных

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

Модуль 1: Python Core
4 уровень , 9 лекция
Открыта

10.1 Локальные переменные функции

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

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

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

Область видимости вложенных функций: Если функция определена внутри другой функции, её переменные доступны только внутри этой вложенной функции.

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

Встроенная область видимости: Это специальная область видимости, которая включает в себя все встроенные объекты и функции Python, доступные по умолчанию (например, print() и len()).

Правило LEGB

Для разрешения переменных Python использует правило LEGB, которое определяет порядок, в котором интерпретатор ищет переменные:

  • L (Local) — Сначала поиск в локальной области видимости.
  • E (Enclosed) — Затем в областях видимости всех вложенных функций, от ближайшей к внешней.
  • G (Global) — Далее в глобальной области видимости.
  • B (Built-in) — Наконец, во встроенной области видимости.

Примеры использования


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

def outer():
    y = "outer local"  # Локальная переменная внешней функции
    def inner():
        z = "inner local"  # Локальная переменная вложенной функции
        print(x)  # Выводит "global"
        print(y)  # Выводит "outer local"
        print(z)  # Выводит "inner local"
    inner()

outer()

Переменная z доступна только внутри функции inner().

Переменная y доступна внутри функции outer() и во всех функциях, объявленных внутри неё.

Переменная x доступна везде в текущем файле (модуле).

10.2 Доступ к глобальным переменным: global x

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

При попытке записать что-то во внешнюю переменную будет создана локальная переменная с таким же именем, а доступ к внешней переменной будет потерян.

Пример:


x = 10

def change_global():
    print(x)  # Это вызовет ошибку, так как x будет считаться локальной переменной после присвоения
    x = 20  # Тут создастся локальная переменная x
    print(x)  # Выведет 20 (идёт обращение к локальной переменной x)
        
change_global()
print(x)  # Выведет 10

Этот пример не работает и вызовет ошибку UnboundLocalError, потому что интерпретатор Python сначала видит присвоение x = 20 и считает, что x является локальной переменной. Однако, когда интерпретатор доходит до строки print(x), он не находит локальной переменной x, так как она ещё не была определена.

Так сделано для безопасности, чтобы локальные переменные случайно не изменили глобальные.

Оператор global

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

Чтобы изменить значение глобальной переменной внутри функции, необходимо объявить эту переменную в начале функции с помощью global. Это даёт функции доступ на запись к переменной:


x = 10

def change_global():
    global x  # Объявляем x как глобальную переменную
    print(x)  # Выведет 10 (идёт обращение к глобальной переменной x)
    x = 20  # Тут присваиваем новое значение глобальной переменной x
    print(x)  # Выведет 20 (идёт обращение к глобальной переменной x)

change_global()
print(x)  # Выведет 20

Использование оператора global позволяет избежать ошибки и правильно управлять глобальными переменными.

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

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

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

10.3 Доступ к не-локальным переменным: nonlocal

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

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

Оператор nonlocal помогает избежать создания новой локальной переменной во вложенной функции, когда необходимо изменить переменную, определённую во внешней функции. Без использования nonlocal изменения затронут только локальную переменную внутренней функции, не влияя на переменную во внешней функции.

Пример:


def outer():
    count = 0

    def inner():
        nonlocal count
        count += 1
        return count

    return inner

counter = outer()
print(counter())  # Выведет 1

Вот более практический пример использования nonlocal для создания счётчика:


def create_counter():
    count = 0
    
    def increment():
        nonlocal count
        count += 1
        return count
    
    return increment

counter = create_counter()
print(counter())  # Выведет 1
print(counter())  # Выведет 2
print(counter())  # Выведет 3

Этот пример демонстрирует, как nonlocal может быть использован в реальных сценариях для создания функции, которая сохраняет своё состояние между вызовами.

2
Задача
Модуль 1: Python Core, 4 уровень, 9 лекция
Недоступна
Использование глобальной переменной
Использование глобальной переменной
2
Задача
Модуль 1: Python Core, 4 уровень, 9 лекция
Недоступна
Использование nonlocal переменной
Использование nonlocal переменной
Комментарии (8)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
mila Уровень 20
6 апреля 2025
да, чёто както странно

print(x)  # Это вызовет ошибку, так как x будет считаться локальной переменной после присвоения
мы же только читаем тут х, почему будет ошибка??
Alexander Polovnev Уровень 1
9 июня 2025
Python анализирует всю функцию целиком при её определении. И он видит присваивание x = 20, поэтому считает x локальной переменной во всей функции change_global. Даже если print(x) написан до строки x = 20, Python считает, что x внутри этой функции — локальная переменная. Но в момент вызова первого print(x) переменная x ещё не получила значение, поэтому: возникает UnboundLocalError - нельзя использовать локальную переменную до её первого присваивания.
SWK Уровень 26
17 марта 2025
После того, как выяснилось, что вот в этом месте

    print(x)  # Это вызовет ошибку, так как x будет считаться локальной переменной после присвоения
    x = 20  # Тут создастся локальная переменная x
интерпретатор сначала увидит вторую строчку, а потом уже первую, уместно было бы пояснить за интерпретатор. Если он сначала просматривает в тексте определения, а потом вызовы функций, то какой-то он уже многопроходный интерпретатор, чтобы не сказать компилятор во что-нибудь экзотическое.
Votvlad Уровень 24
9 февраля 2025
Простите, ничего не понял. Во 2-й задаче, после вызова внутренней функции, x, вроде как, должен стать равным 15. А программа ничего не вернула и ответ засчитан как верный.
Шамиль Ахметов Уровень 31
22 апреля 2025
нужно вызвать внешнюю функцию
shinobi Уровень 19
22 июля 2025
Нужно чтобы внутренняя функция меняла X, а внешняя функция вызывала внутри себя внутрненнюю. Итого порядок такой: print вызвает внешнюю функцию > внешняя функция вызывает внутреннюю функцию > внутренняя функция меняет X
Dmitry Ryabov Уровень 23
21 января 2025
Чем принципиально отличается Пример 1 от Пример 2 , кроме как изменением имён функций:

#Пример 1
def outer():
    count = 0

    def inner():
        nonlocal count
        count += 1
        return count

    return inner

counter = outer()
print(counter())  # Выведет 1

#Пример 2
def create_counter():
    count = 0

    def increment():
        nonlocal count
        count += 1
        return count

    return increment

counter = create_counter()
print(counter())  # Выведет 1
print(counter())  # Выведет 2
print(counter())  # Выведет 3
Стоит, наверно, сюда вставить какой-то более яркий пример, который показывает использование оператора nonlocal.
Anonymous #2637008 Уровень 17 Expert
30 декабря 2024
в веб версии задача Использование nonlocal переменной прошла тест без использования оператора def во вложенной функции. Пример :

def outer_function():
    x = ...
    inner_function():
...