Локальные и глобальные переменные
В программировании особое внимание уделяется концепции о локальных и глобальных переменных, а также связанное с ними представление об областях видимости. Соответственно, локальные переменные видны только в локальной области видимости, которой может выступать отдельно взятая функция. Глобальные переменные видны во всей программе. «Видны» – значит, известны, доступны. К ним можно обратиться по имени и получить связанное с ними значение.
К глобальной переменной можно обратиться из локальной области видимости. К локальной переменной нельзя обратиться из глобальной области видимости, потому что локальная переменная существует только в момент выполнения тела функции. При выходе из нее, локальные переменные исчезают. Компьютерная память, которая под них отводилась, освобождается. Когда функция будет снова вызвана, локальные переменные будут созданы заново.
Вернемся к нашей программе из прошлого урока, немного упростив ее для удобства:
def rectangle(): a = float(input("Ширина: ")) b = float(input("Высота: ")) print("Площадь: %.2f" % (a * b)) def triangle(): a = float(input("Основание: ")) h = float(input("Высота: ")) print("Площадь: %.2f" % (0.5 * a * h)) figure = input("1-прямоугольник, 2-треугольник: ") if figure == '1': rectangle() elif figure == '2': triangle()
Сколько здесь переменных? Какие из них являются глобальными, а какие – локальными?
Здесь пять переменных. Глобальной является только figure . Переменные a и b из функции rectangle , а также a и h из triangle – локальные. При этом локальные переменные с одним и тем же идентификатором a , но объявленные в разных функциях, – разные переменные.
Следует отметить, что идентификаторы rectangle и triangle , хотя и не являются именами переменных, а представляют собой имена функций, также имеют область видимости. В данном случае она глобальная, так как функции объявлены непосредственно в основной ветке программы.
В приведенной программе к глобальной области видимости относятся заголовки объявлений функций, объявление и присваивание переменной figure , конструкция условного оператора.
К локальной области относятся тела функций. Если, находясь в глобальной области видимости, мы попытаемся обратиться к локальной переменной, то возникнет ошибка:
… elif figure == '2': triangle() print(a)
1-прямоугольник, 2-треугольник: 2 Основание: 4 Высота: 5 Площадь: 10.00 Traceback (most recent call last): File "test.py", line 17, in print(a) NameError: name 'a' is not defined
Однако мы можем обращаться из функций к глобальным переменным:
def rectangle(): a = float(input("Ширина %s: " % figure)) b = float(input("Высота %s: " % figure)) print("Площадь: %.2f" % (a * b)) def triangle(): a = float(input("Основание %s: " % figure)) h = float(input("Высота %s: " % figure)) print("Площадь: %.2f" % (0.5 * a * h)) figure = input("1-прямоугольник, 2-треугольник: ") if figure == '1': rectangle() elif figure == '2': triangle()
1-прямоугольник, 2-треугольник: 1 Ширина 1: 6.35 Высота 1: 2.75 Площадь: 17.46
В данном случае из тел функций происходит обращение к имени figure , которое, из-за того, что было объявлено в глобальной области видимости, видимо во всей программе.
Наши функции не совсем идеальны. Они должны вычислять площади фигур, но выводить результат на экран им не следовало бы. Вполне вероятна ситуация, когда результат нужен для внутренних нужд программы, для каких-то дальнейших вычислений, а выводить ли его на экран – вопрос второстепенный.
Если функции не будут выводить, а только вычислять результат, то его надо где-то сохранить для дальнейшего использования. Для этого подошли бы глобальные переменные. В них можно записать результат. Напишем программу вот так:
def rectangle(): a = float(input("Ширина: ")) b = float(input("Высота: ")) result = a * b def triangle(): a = float(input("Основание: ")) h = float(input("Высота: ")) result = 0.5 * a * h result = 0 figure = input("1-прямоугольник, 2-треугольник: ") if figure == '1': rectangle() elif figure == '2': triangle() print("Площадь: %.2f" % result)
Итак, мы ввели в программу глобальную переменную result и инициировали ее нулем. В функциях ей присваивается результат вычислений. В конце программы ее значение выводится на экран. Мы ожидаем, что программа будет прекрасно работать. Однако…
1-прямоугольник, 2-треугольник: 2 Основание: 6 Высота: 4.5 Площадь: 0.00
… что-то пошло не так.
Дело в том, что в Python присвоение значения переменной совмещено с ее объявлением. (Во многих других языках это не так.) Поэтому, когда имя result впервые упоминается в локальной области видимости, и при этом происходит присваивание ей значения, то создается локальная переменная result . Это другая переменная, никак не связанная с глобальной result .
Когда функция завершает свою работу, то значение локальной result теряется, а глобальная не была изменена.
Когда мы вызывали внутри функции переменную figure , то ничего ей не присваивали. Наоборот, мы запрашивали ее значение. Интерпретатор Питона искал ее значение сначала в локальной области видимости и не находил. После этого шел в глобальную и находил.
В случае с result он ничего не ищет. Он выполняет вычисления справа от знака присваивания, создает локальную переменную result , связывает ее с полученным значением.
На самом деле можно принудительно обратиться к глобальной переменной. Для этого существует команда global :
def rectangle(): a = float(input("Ширина: ")) b = float(input("Высота: ")) global result result = a * b def triangle(): a = float(input("Основание: ")) h = float(input("Высота: ")) global result result = 0.5 * a * h result = 0 figure = input("1-прямоугольник, 2-треугольник: ") if figure == '1': rectangle() elif figure == '2': triangle() print("Площадь: %.2f" % result)
В таком варианте программа будет работать правильно.
Однако менять значения глобальных переменных в теле функции – плохая практика. В больших программах трудно отследить, где, какая функция и почему изменила их значение. Программист смотрит на исходное значение глобальной переменной и может подумать, что оно остается таким же. Сложно заметить, что какая-то функция поменяла его. Подобное ведет к логическим ошибкам.
Чтобы избавиться от необходимости использовать глобальные переменные, для функций существует возможность возврата результата своей работы в основную ветку программы. И уже это полученное из функции значение можно присвоить глобальной переменной в глобальной области видимости. Это делает программу более понятной.
Как функция принимает и возвращает данные, будет рассмотрено в следующих уроках.
Практическая работа
В языке Python можно внутри одной функции определять другую. Напишите программу по следующему описанию.
В основной ветке программы вызывается функция cylinder() , которая вычисляет площадь цилиндра. В теле cylinder определена функция circle , вычисляющая площадь круга по формуле πr 2 . В теле cylinder у пользователя спрашивается, хочет ли он получить только площадь боковой поверхности цилиндра, которая вычисляется по формуле 2πrh, или полную площадь цилиндра. В последнем случае к площади боковой поверхности цилиндра должен добавляться удвоенный результат вычислений функции circle() .
Как вы думаете, можно ли из основной ветки программы вызвать функцию, вложенную в другую функцию? Почему?
Примеры решения и дополнительные уроки в pdf-версии курса
X Скрыть Наверх
Python. Введение в программирование
Python Глобальные переменные
Переменные, созданные вне функции (как и во всех приведенных выше примерах), называются глобальными переменными.
Глобальные переменные могут использоваться всеми, как внутри функций, так и снаружи.
Пример
Создайте переменную вне функции и используйте ее внутри функции
def myfunc():
 print(«Python это » + x)
Если вы создадите переменную с тем же именем внутри функции, эта переменная будет локальной и может использоваться только внутри функции. Глобальная переменная с тем же именем останется прежней, глобальной и с исходным значением.
Пример
Создайте переменную внутри функции с тем же именем, что и у глобальной переменной.
def myfunc():
x = «фантастика»
print(«Python это » + x)
print(«Python это » + x)
Глобальное ключевое слово
Обычно, когда вы создаете переменную внутри функции, эта переменная является локальной и может использоваться только внутри этой функции.
Чтобы создать глобальную переменную внутри функции, вы можете использовать ключевое слово global .
Пример
Если вы используете ключевое слово global переменная принадлежит к глобальной области видимости:
def myfunc():
global x
x = «фантастика»
print(«Python это » + x)
Кроме того, используйте ключевое слово global если вы хотите изменить глобальную переменную внутри функции.
Пример
Чтобы изменить значение глобальной переменной внутри функции, обратитесь к переменной с помощью ключевого слова global :
def myfunc():
global x
x = «фантастика»
print(«Python это » + x)
Мы только что запустили
SchoolsW3 видео
ВЫБОР ЦВЕТА
курс сегодня!
Сообщить об ошибке
Если вы хотите сообщить об ошибке или внести предложение, не стесняйтесь отправлять на электронное письмо:
Ваше предложение:
Спасибо Вам за то, что помогаете!
Ваше сообщение было отправлено в SchoolsW3.
ТОП Учебники
ТОП Справочники
ТОП Примеры
Получить сертификат
SchoolsW3 оптимизирован для бесплатного обучения, проверки и подготовки знаний. Примеры в редакторе упрощают и улучшают чтение и базовое понимание. Учебники, ссылки, примеры постоянно пересматриваются, чтобы избежать ошибок, но не возможно гарантировать полную правильность всего содержания. Некоторые страницы сайта могут быть не переведены на РУССКИЙ язык, можно отправить страницу как ошибку, так же можете самостоятельно заняться переводом. Используя данный сайт, вы соглашаетесь прочитать и принять Условия к использованию, Cookies и политика конфиденциальности.
Руководство по глобальным переменным
Переменная, доступ к которой можно получить из любого места в коде, называется глобальной. Ее можно определить вне блока. Другими словами, глобальная переменная, объявленная вне функции, будет доступна внутри нее.
С другой стороны, переменная, объявленная внутри определенного блока кода, будет видна только внутри этого же блока — она называется локальной.
Разберемся с этими понятиями на примере.
Пример локальных и глобальных переменных
def sum(): a = 10 # локальные переменные b = 20 c = a + b print("Сумма:", c) sum()Переменная объявлена внутри функции и может использоваться только в ней. Получить доступ к этой локальной функции в других нельзя.
Для решения этой проблемы используются глобальные переменные.
Теперь взгляните на этот пример с глобальными переменными:
a = 20 # определены вне функции b = 10 def sum(): c = a + b # Использование глобальных переменных print("Сумма:", c) def sub(): d = a - b # Использование глобальных переменных print("Разница:", d) sum() sub()Сумма: 30 Разница: 10В этом коде были объявлены две глобальные переменные: a и b . Они используются внутри функций sum() и sub() . Обе возвращают результат при вызове.
Если определить локальную переменную с тем же именем, то приоритет будет у нее. Посмотрите, как в функции msg это реализовано.
def msg(): m = "Привет, как дела?" print(m) msg() m = "Отлично!" # глобальная переменная print(m)Привет, как дела? Отлично!Здесь была объявлена локальная переменная с таким же именем, как и у глобальной. Сперва выводится значение локальной, а после этого — глобальной.
Ключевое слово global
Python предлагает ключевое слово global , которое используется для изменения значения глобальной переменной в функции. Оно нужно для изменения значения. Вот некоторые правила по работе с глобальными переменными.
Правила использования global
- Если значение определено на выходе функции, то оно автоматически станет глобальной переменной.
- Ключевое слово global используется для объявления глобальной переменной внутри функции.
- Нет необходимости использовать global для объявления глобальной переменной вне функции.
- Переменные, на которые есть ссылка внутри функции, неявно являются глобальными.
Пример без использования глобального ключевого слова.
c = 10 def mul(): c = c * 10 print(c) mul()line 5, in mul c = c * 10 UnboundLocalError: local variable 'c' referenced before assignmentЭтот код вернул ошибку, потому что была предпринята попытка присвоить значение глобальной переменной. Изменять значение можно только с помощью ключевого слова global .
c = 10 def mul(): global c c = c * 10 print("Значение в функции:", c) mul() print("Значение вне функции:", c)Значение в функции: 100 Значение вне функции: 100Здесь переменная c была объявлена в функции mul() с помощью ключевого слова global . Ее значение умножается на 10 и становится равным 100. В процессе работы программы можно увидеть, что изменение значения внутри функции отражается на глобальном значении переменной.
Глобальные переменные в модулях Python
Преимущество использования ключевого слова global — в возможности создавать глобальные переменные и передавать их между модулями. Например, можно создать name.py, который бы состоял из глобальных переменных. Если их изменить, то изменения повлияют на все места, где эти переменные встречаются.
1. Создаем файл name.py для хранения глобальных переменных:
Кратко о локальных и глобальных переменных
Подробнее о namespace читайте в следующем разделе. Здесь будет короткое описание основных моментов.
Область видимости (пространство имен) - область, где хранятся переменные. Здесь определяются переменные и делают поиск имен.
Операция = связывает имена с областью видимости (пространством имен)
Пока мы не написали ни одной функции, все переменные в программе глобальные.
Глобальные переменные видны во всех функциях программы. Они должны быть сначала созданы, а потом их можно читать и менять.
Создаются переменные присвоением =
Обычно пишут программу так:
a = 1 # создали раньше, чем ее использовали def f(): print(a) # читаем глобальную переменную а (не изменяя ее значения) f() # тут (дальше) мы использовали переменную аЭтот код будет работать так же:
def f(): print(a) # глобальная переменная а a = 1 # создали раньше, чем ее использовали f() # тут (дальше) мы использовали переменную аНапечатает 1. Глобальная переменная а сначала была создана, а потом была вызвана функция f(). В функции f() видна глобальная переменная a.
Особенность интерптерируемого языка. Сначала - это раньше в процессе выполнения, а не "на строке с меньшим номером".
Локальная переменная создается внутри функции или блока (например, if или while). Локальная переменная видна только внутри того блока (функции), где была создана.
def f(): a = 1 # локальная переменная функции f f() print(a) # ошибка, локальная переменная а не видна вне функции f.Ошибка "builtins.NameError: name 'a' is not defined"
- Локальные переменные создаются =.
- Каждый вызов функции создает локальную переменную (свою, новую) (каждый вызов функции создает свой новый namespace)
- после завершения функции ее локальные переменные уничтожаются.
- аргументы функции тоже являются локальными переменными (при вызове функции идет = параметру значения).
Итого: Если в функции было =, то мы создали локальную переменную. Если = не было, то читаем глобальную переменную.
Можно создавать в разных функциях локальные переменные с одинаковыми именами. В функциях foo и bar создали переменные с одинаковыми именами а.
Можно (но не надо так делать!) создавать локальную переменную с тем же именем, что и глобальную. pylint поможет найти такие переменные.
def f(): a = 1 # создана локальная переменная а=1 print(a, end=' ') # печатаем локальную переменную а=1 a = 0 # создана глобальная переменная а=0 f() print(a) # печатаем глобальную переменную а=0
- создается глобальная переменная а = 0
- вызывается f()
- в f создается локальная переменная а = 1 (теперь нельзя доступиться из функции f к глобальной переменной a)
- в f печатается локальная переменная a = 1
- завершается f
- печатается глобальная переменная а = 0
Переменная в функции будет считаться локальной, если она будет создана внутри условного оператора, который никогда не выполнится:
def f(): print(a) # UnboundLocalError: local variable 'a' referenced before assignment if False: a = 0 # тут создаем локальную переменную а внутри функции f a = 1 # глобальная переменная а f()
global говорит, что переменная относится к глобальному namespace. (В этот момент переменная НЕ создается). Переменную можно создать позже.
def f(): global a a = 1 print(a, end=' ') a = 0 f() print(a)
выведет "1 1", т.к. значение глобальной переменной будет изменено внутри функции.
Рекурсивный вызов функции
Так как каждый вызов функции создает свое собственное пространство имен, можно писать функции рекурсивно.
Например, n! = n * (n-1)!, 0! = 1. Запишем это математическое определение факториала в виде кода.
def fact(n): if n == 0: return 1 return n * fact(n-1) print(fact(5))
При вызове fact(5) создается namespace c n=5, далее идет вызов f(4) и создается еще один namespace, в нем n=4 (это другая переменная n, она в другом пространстве имен и та n=5 из этого пространства не доступна).
Вложенные области видимости
Можно определять одну функцию внутри другой.
Чтение переменной внутри функции. Ищем имя:
- в локальной области видимости функции;
- в локальных областях видимости объемлющих функций изнутри наружу;
- в глобальной области видимости модуля;
- в builtins (встроенная область видимости).
x = value внутри функции:
- создает или изменяет имя х в текущей локальной области видимости функции;
- если был unlocal x , то = создает или изменяет имя в ближайшей области видимости объемлющей функции.
- если был global x , то = создает или изменяет имя в области видимости объемлющего модуля.
X = 99 # Имя в глобальной области видимости: не используется def f1(): X = 88 # Локальное имя в объемлющей функции def f2(): print(X) # Обращение к переменной во вложенной функции f2() f1() # Выведет 88: локальная переменная в объемлющей функции f2() # Ошибка! функция f2 здесь не видна!
В f2() нельзя изменить значение Х, принадлежащей функции f1(). Вместо этого будет создана еще одна локальная переменная, но уже в пространстве имен функции f2(). Напечатает 77 88 :
X = 99 # Имя в глобальной области видимости: не используется def f1(): X = 88 # Локальное имя в объемлющей функции def f2(): X = 77 # создаем локальную переменную print(X) # 77 - обращение к локальной переменной функции f2() f2() print(X) # 88 - обращение к локальной переменной функции f1() f1()
Если нужно изменять значение переменной Х, которая принадлежит пространству имен объемлющей (enclosed) функции, то добавляют unlocal
X = 99 # Имя в глобальной области видимости: не используется def f1(): X = 88 # Локальное имя в функции f1 def f2(): unlocal X # X принадлежит объемлющей функции X = 77 # изменяем переменную функции f1 print(X) # 77 - обращение к локальной переменной объемлющей функции f1() f2() print(X) # 77 - обращение к локальной переменной функции f1() f1()
Правило LEGB
При определении, к какому namespace относится имя, используют правило LEGB:
- Когда внутри функции выполняется обращение к неизвестному имени, интерпретатор пытается отыскать его в четырех областях видимости – в локальной (local, L), затем в локальной области любой объемлющей инструк- ции def (enclosing, E) или в выражении lambda, затем в глобальной (global, G) и, наконец, во встроенной (built-in, B).
- Поиск завершается, как только будет найдено первое подходящее имя.
- Если требуемое имя не будет найдено, интерпретатор выведет сообщение об ошибке.
results matching " "
No results matching " "
