Внутри функции можно использовать переменные, объявленные вне этой функции
def f(): print (a) a = 1 f() |
Здесь переменной a
присваивается значение 1, и функция f
печатает это значение, несмотря на то, что выше функции f
эта переменная
не инициализируется. Но в момент вызова функции f
переменной a
уже присвоено значение, поэтому функция f
может вывести его на экран.
Такие переменные (объявленные вне функции, но доступные внутри функции) называются глобальными.
Но если инициализировать какую-то переменную внутри функции, использовать эту переменную вне функции не удастся. Например:
def f(): a = 1 f() print (a) |
Получим NameError: name 'a' is not defined
. Такие переменные, объявленные внутри функции,
называются локальными. Эти переменные становятся недоступными после выхода из функции.
Интересным получится результат, если попробовать изменить значение глобальной переменной внутри функции:
def f(): a = 1 print (a) a = 0 f() print (a) |
Будут выведены числа 1 и 0. То есть несмотря на то, что значение переменной a
изменилось внутри функции, то вне функции оно осталось прежним! Это сделано в целях
“защиты” глобальных переменных от случайного изменения из функции
(например, если функция будет вызвана из цикла по переменной i
, а в этой функции
будет использована переменная i
также для организации цикла, то эти переменные должны
быть различными). То есть если внутри функции модифицируется значение некоторой переменной,
то переменная с таким именем становится локальной переменной, и ее модификация не приведет
к изменению глобальной переменной с таким же именем.
Более формально: интерпретатор Питон считает переменную локальной, если внутри
нее есть хотя бы одна инструкция, модифицирующая значение переменной (это может быть
оператор =
, +=
и т.д., или использование этой переменной
в качестве параметра цикла for
, то эта переменная считается локальной
и не может быть использована до инициализации. При этом даже если инструкция,
модицифицирующая переменную никогда не будет выполнена: интерпретатор это проверить
не может, и переменная все равно считается локальной. Пример:
def f(): print (a) if False : a = 0 a = 1 f() |
Возникает ошибка: UnboundLocalError: local variable 'a' referenced before assignment
.
А именно, в функции f
идентификатор a
становится локальной переменной,
т.к. в функции есть команда, модифицирующая переменную a
, пусть даже никогда и
не выполняющийся (но интерпретатор не может это отследить). Поэтому вывод переменной a
приводит к обращению к неинициализированной локальной переменной.
Чтобы функция могла изменить значение глобальной переменной, необходимо объявить эту переменную
внутри функции, как глобальную, при помощи ключевого слова global
:
def f(): global a a = 1 print (a) a = 0 f() print (a) |
В этом примере на экран будет выведено 1 1, так как переменная a
объявлена, как глобальная,
и ее изменение внутри функции приводит к тому, что и вне функции переменная
будет доступна.
Тем не менее, лучше не изменять значения глобальных переменных внутри функции. Если функция должна поменять какую-то переменную, то как правило это лучше сделать, как значение, возвращаемое функцией.
Если нужно, чтобы функция вернула не одно значение, а два или более, то для этого функция может вернуть кортеж из двух или нескольких значений:
return (a, b) |
Тогда результат вызова функции тоже нужно присваивать кортежу:
(n, m) = f(a, b) |