Что происходит, если в функции используется переменная, которая не была явно объявлена как глобальная?

Если внутри функции используется переменная, которая не была объявлена как global, Python будет искать ее в следующих областях видимости (по порядку LEGB):

  • Local (локальная область видимости функции)
  • Enclosing function locals (локальная область видимости объемлющей функции, если таковая имеется)
  • Global (глобальная область видимости модуля)
  • Built-in (встроенная область видимости Python)

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


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

1. Поиск в локальной области видимости: Сначала Python ищет переменную в локальной области видимости функции. Это включает в себя любые переменные, которые были явно определены внутри функции (например, `x = 5` или переменные, переданные в качестве аргументов функции).
2. Чтение переменной (без присваивания): Если переменная используется только для чтения (например, `print(x)`), и она не найдена в локальной области видимости, Python продолжит поиск во включающих областях видимости, таких как область видимости внешней функции (если функция вложена в другую функцию) и, наконец, в глобальной области видимости модуля. Если переменная не найдена нигде, возникнет ошибка `NameError`.
3. Присваивание переменной (=): Если переменной присваивается значение (например, `x = 10`), и она не была объявлена как `global`, Python предполагает, что это новая локальная переменная. Это означает, что Python создаст новую переменную с таким именем в локальной области видимости функции. Если переменная с таким же именем существует в глобальной области видимости, ее значение останется неизменным, и локальная переменная с тем же именем скроет глобальную переменную внутри функции.
4. Модификация (+=, -=, *= и т.д.): Если переменная модифицируется (например, `x += 1`), и она не была объявлена как `global`, и ее нет в локальной области видимости, Python также предположит, что это новая локальная переменная. Но, в отличие от простого присваивания, Python не может создать локальную переменную, не зная ее начального значения. Поэтому, в данном случае, возникнет ошибка `UnboundLocalError: local variable 'x' referenced before assignment`. Это происходит потому, что Python пытается использовать значение переменной перед тем, как оно было присвоено в локальной области видимости.

Пример:
    x = 5  # Глобальная переменная

    def my_function():
        print(x)  # Чтение глобальной переменной x (выведет 5)
        x = 10  # Создает локальную переменную x, не изменяет глобальную
        print(x)  # Выведет 10 (локальную x)
        # x += 1 # UnboundLocalError

    my_function()
    print(x)  # Выведет 5 (глобальную x)
  
Чтобы изменить глобальную переменную внутри функции, нужно использовать ключевое слово `global`:
    x = 5

    def my_function():
        global x
        print(x)  # Выведет 5 (глобальную x)
        x = 10  # Изменяет глобальную переменную x
        print(x)  # Выведет 10 (глобальную x)

    my_function()
    print(x)  # Выведет 10 (глобальную x)
  
0