Глобальные переменные в Python
Узнайте, как работают глобальные переменные в Python, как изменять их с помощью ключевого слова global, избегать ошибок UnboundLocalError и когда использовать альтернативы.
Глобальные переменные в Python — это переменные, объявленные вне каких-либо функций. Они существуют на протяжении всего времени работы программы и могут быть прочитаны из любого места — однако для их изменения внутри функции требуется ключевое слово global. На этой странице рассматривается, как работают глобальные переменные, каких ловушек следует избегать и когда лучше выбрать другие подходы.
Что такое глобальные переменные?
Глобальная переменная создаётся на уровне модуля (верхнего уровня) — вне каких-либо функций или классов. Любой код в том же модуле может её прочитать без каких-либо специальных объявлений.
Python использует правило LEGB для разрешения имён: поиск идёт по порядку — Local → Enclosing → Global → Built-in (Локальная → Объемлющая → Глобальная → Встроенная). Глобальная переменная находится на уровне «G», поэтому любая функция может её найти, исчерпав собственные локальную и объемлющую области видимости. Полное объяснение всех четырёх уровней см. в разделе Область видимости Python.
Чтение и изменение глобальных переменных
Чтение глобальной переменной (всегда работает)
По умолчанию функция может читать любую глобальную переменную без специального синтаксиса:
language = "Python"
def print_language():
print(language) # reads the global
print_language() # Output: PythonКлючевое слово global — обязательно для изменения
Если попытаться присвоить значение переменной внутри функции, Python создаст новую локальную переменную вместо того, чтобы обновить глобальную. Чтобы изменить глобальную переменную, необходимо объявить её с помощью ключевого слова global:
counter = 0
def increment():
global counter # tell Python we mean the global 'counter'
counter += 1
print("Counter:", counter)
increment() # Output: Counter: 1
increment() # Output: Counter: 2
print(counter) # Output: 2Без global counter строка counter += 1 вызовет UnboundLocalError, потому что Python попытается прочитать локальную переменную с именем counter до того, как она была присвоена.
Ловушка UnboundLocalError
Это наиболее распространённая ошибка при работе с глобальными переменными. Как только Python видит любое присваивание имени внутри функции, он считает это имя локальным во всей функции — даже для строк, расположенных до присваивания:
x = 10
def broken():
print(x) # ERROR — Python sees the assignment below and marks x as local
x = 20
broken()
# UnboundLocalError: local variable 'x' referenced before assignmentИсправить это можно, добавив global x в начало функции, если вам действительно нужно изменить глобальную переменную, или переименовав локальную переменную, если нужна независимая копия.
Затенение переменных
Присваивание имени внутри функции без ключевого слова global создаёт локальную переменную, которая затеняет глобальную — при этом глобальная не изменяется:
count = 100
def show_count():
count = 5 # local variable — shadows the global 'count'
print("Inside function:", count) # 5
show_count()
print("Outside function:", count) # 100 — global is unchangedЗатенение не является ошибкой, но может вносить путаницу. Используйте различимые имена, чтобы намерение было очевидным.
global во вложенных функциях
Если нужно обратиться к глобальной переменной уровня модуля из внутренней (вложенной) функции, используйте global — не nonlocal. nonlocal обращается только к области видимости непосредственно объемлющей функции, но не к уровню модуля:
total = 0
def outer():
def inner():
global total # reaches module scope
total += 10
inner()
outer()
outer()
print("total:", total) # Output: total: 20Сравните это с nonlocal, который изменяет переменную объемлющей функции, не затрагивая глобальную переменную уровня модуля:
x = "global"
def outer():
x = "outer"
def inner():
nonlocal x # modifies outer()'s x, not the module-level x
x = "inner"
inner()
print("outer x after inner():", x) # inner
outer()
print("global x after outer():", x) # global — unchangedПодробнее о nonlocal см. в разделе Область видимости Python.
Константы на уровне модуля — правильный случай применения
Наиболее обоснованное применение глобальных переменных уровня модуля — это константы: значения, которые задаются один раз и никогда не изменяются во время выполнения. По соглашению их записывают в UPPER_SNAKE_CASE:
MAX_RETRIES = 3
DEFAULT_TIMEOUT = 30
def connect(host, retries=MAX_RETRIES, timeout=DEFAULT_TIMEOUT):
print(f"Connecting to {host} with {retries} retries, timeout={timeout}s")
connect("db.example.com")
# Output: Connecting to db.example.com with 3 retries, timeout=30sКонстантам никогда не нужно ключевое слово global, поскольку они только читаются, но никогда не переприсваиваются.
Рекомендации
1. Отдавайте предпочтение аргументам функций и возвращаемым значениям
Передача данных через сигнатуры функций делает код более удобным для тестирования и понимания. Эта чистая функция проще, чем использование изменяемого глобального счётчика counter:
def increment(counter):
return counter + 1
counter = 0
counter = increment(counter)
counter = increment(counter)
print("counter:", counter) # Output: counter: 22. Оставляйте глобальные переменные для истинных констант уровня модуля
Используйте глобальные переменные для значений, которые действительно фиксированы на протяжении всего выполнения программы (MAX_CONNECTIONS, APP_VERSION, конфигурация, загружаемая однажды при запуске). Избегайте изменяемых глобальных переменных, меняющихся со временем.
3. Используйте описательные имена в формате UPPER_SNAKE_CASE для констант
Имя вроде MAX_RETRIES сразу распознаётся как константа уровня модуля. Имя вроде r — нет.
4. Инициализируйте переменные перед использованием
Объявляйте все глобальные переменные в начале модуля, до любых функций, которые их используют. Это предотвращает NameError, если функция будет вызвана до того, как переменная была бы определена иным способом.
5. Будьте осторожны с потоками
Если несколько потоков вызывают функции, изменяющие одну и ту же глобальную переменную, возникает состояние гонки. Защищайте общее изменяемое состояние с помощью threading.Lock или переработайте код, чтобы избежать совместного состояния вовсе. Общий обзор типов переменных в Python см. в разделе Переменные Python.
Итог
| Ситуация | Что делать |
|---|---|
| Чтение глобальной переменной внутри функции | Ничего особенного не нужно |
| Изменение глобальной переменной внутри функции | Добавьте global <name> в начало функции |
| Изменение переменной объемлющей функции | Используйте nonlocal <name> |
| Передача фиксированного значения во множество функций | Объявите константу уровня модуля в UPPER_SNAKE_CASE |
| Передача изменяемого состояния между функциями | Отдайте предпочтение аргументам функций и возвращаемым значениям |