Часто задаваемые вопросы
Некоторые не совсем очевидные вещи, с которыми сталкиваются начинающие программисты Python.
Почему я получаю исключение UnboundLocalError, хотя переменная имеет значение?
Может показаться неожиданным получить UnboundLocalError в ранее работающем коде, в который добавили операцию присваивания где-то внутри функции.
UnboundLocalError:
Это происходит потому, что, когда вы делаете присваивание переменной в области видимости, она становится локальной в этой области и скрывает другие переменные с таким же именем во внешних областях.
Когда последняя инструкция в foo присваивает новое значение переменной x, компилятор решает, что это локальная переменная. Следовательно, когда более ранний print пытается напечатать неинициализированную переменную, возникает ошибка.
В примере выше можно получить доступ к переменной, объявив её глобальной:
Вы можете сделать подобную вещь во вложенной области видимости использованием ключевого слова nonlocal:
В Python, переменные, на которые только ссылаются внутри функции, считаются глобальными. Если переменной присваивается новое значение где-либо в теле функции, считается, что она локальная, и, если вам нужно, то нужно явно указывать её глобальной.
Хотя это немного удивительно на первый взгляд, это легко объяснимо. С одной стороны, требование global для присваиваемых переменных предотвращает непреднамеренные побочные эффекты в bar. С другой стороны, если global был обязательным для всех глобальных ссылок, вы бы использовали global все время. Вы должны были бы объявить как глобальную каждую ссылку на встроенную функцию или компонент импортируемого модуля.
Почему анонимные функции (lambda), определенные в цикле с разными значениями, возвращают один и тот же результат?
Например, вы написали следующий код:
x**2 . Можно ожидать, что, будучи вызванными, они вернут, соответственно, 0, 1, 4, 9, и 16. Однако, вы увидите, что все они возвращают 16:
Это случается, поскольку x не является локальной для lambda, а определена во внешней области видимости, и получается тогда, когда она вызывается - а не когда определяется.
В конце цикла, x=4, поэтому все функции возвращают 4**2 , то есть 16. Это можно также проверить, изменив значение x и посмотрев на результат:
n=x создаёт локальную для функции переменную n и вычисляется в момент определения функции:
Как организовать совместный доступ к глобальным переменным для нескольких модулей?
Канонический способ организовать подобный доступ - это создать отдельный модуль (часто называемый config или cfg). Просто добавьте import config в каждый модуль приложения. При этом модуль становится доступен через глобальное имя. Поскольку существует только один экземпляр модуля, любые изменения, произведённые в модуле отражаются везде. Например:
mod.py:
main.py:
По тем же соображениям, модули можно использовать как основу для имплементации синглтона.
Как правильнее использовать импортирование?
В общих случаях не используйте from modulename import *. Это засоряет пространство имён того, кто импортирует. Некоторые люди избегают этой идиомы даже для тех немногих модулей, которые были спроектированны, чтобы так импортироваться. Это такие модули как Tkinter и threading.
Импортируйте модули в начале файла. Это отвечает на вопрос, какие модули требует Ваш код и находится ли имя модуля в области видимости. Запись по одному импорту на строку упрощает добавление и удаление операторов импорта, но множественный импорт будет занимать меньше места на экране.
Хорошая практика, если Вы импортируете модули в следующем порядке:
- стандартные библиотечные модули (например, sys, os, getopt, re)
- модули сторонних разработчиков (всё, что установлено в директории site-packages) -- например, PIL, NumPy и т.д.
- локально созданные модули
Иногда бывает необходимо поместить импорт в функцию или класс, чтобы избежать проблем с циклическим импортом. Gordon McMillan советует:
Циклический импорт отлично работает, если оба модуля используют форму import . Но они терпят неудачу, когда второй модуль хочет извлечь имя из первого (from module import name) и импорт находится на внешнем уровне. Это происходит из-за того, что имена первого модуля ещё недоступны, так как первый модуль занят импортом второго.
В этом случае, если второй модуль используется только в одной функции, то импорт можно легко поместить в эту функцию. К тому времени, как он будет вызван, первый модуль уже закончит инициализацию и второй модуль осуществит свой импорт.
Может оказаться необходимым переместить импорт из начала файла, если один из модулей платформно-зависимый. В этом случае импорт всех модулей в начале файла окажется невозможным. В этой ситуации хорошим решением будет импорт нужных модулей в соответствующем платформно-зависимом коде.
Переносите импорт во вложенные области видимости, такие как определения функций, только если Вы столкнулись с проблемой, например циклического импорта, или если Вы пытаетесь сократить время инициализации модуля.
Эта техника полезна, если многие из импортов не являются необходимыми, и зависят от того, как программа будет исполняться. Вы также можете поместить импорт в функцию, если конкретные модули используются только в этой функции. Обратите внимание, что загрузить модуль в первый раз может оказаться дорого из-за задержки на инициализацию модуля, однако повторные загрузки "бесплатны", они стоят только пары поисков в словарях. Даже если имя модуля исчезло из области видимости, модуль скорее всего до сих пор находится в sys.modules.
Почему значения по умолчанию разделяются между объектами?
Этот тип ошибки часто встречается среди начинающих. Предположим, функция:
В первый раз, когда вы вызываете функцию, mydict содержит одно значение. Второй раз, mydict содержит 2 элемента, поскольку, когда foo() начинает выполняться, mydict уже содержит элемент.
Часто ожидается, что вызов функции создаёт новые объекты для значений по умолчанию. Но это не так. Значения по умолчанию создаются лишь однажды, когда функция определяется. Если этот объект изменяется, как словарь в нашем примере, последующие вызовы функции будут использовать изменённый объект.
По определению, неизменяемые объекты (числа, строки, кортежи и None), безопасны при изменении. Изменение изменяемых объектов, таких как словари, списки, и экземпляры пользовательских классов может привести к неожиданным последствиям.
Поэтому, хорошей практикой является не использовать изменяемые объекты в качестве значений по умолчанию. Вместо этого, используйте None и внутри функции, проверяйте аргумент на None и создавайте новый список/словарь. Например, не пишите:
Но пишите так:
Однако, эта особенность может быть полезна. Когда у вас есть функция, которая долго выполняется, часто применяемая техника - кэширование параметров и результата каждого вызова функции:
Получить такие параметры можно с помощью спецификаторов * и ** в списке аргументов функции; они возвращают кортеж позиционных аргументов и словарь именованых параметров. После этого Вы можете передать их в другую функцию, используя в её вызове * и **:
Если вы написали код:
y изменяет также и x.
Два факта приводят к такому результату:
- Переменные - это просто ссылки на объекты. y = x не создаёт копию списка - это просто создаёт переменную y, которая ссылается на тот же объект, что и x.
- Списки изменяемы.
После вызова append, содержимое объекта было изменено с [] на [10]. Поскольку x и y ссылаются на один и тот же объект, использование любого из них даёт нам [10].
Если мы используем неизменяемые объекты:
мы можем видеть, что x и y больше не равны, поскольку числа неизменяемы, и x = x + 1 не изменяет число 5 путем увеличения. Вместо этого, создаётся новый объект 6 и присваивается переменной x (то есть, изменяется то, на какой объект ссылается x). После этого у нас 2 объекта (6 и 5) и 2 переменные, которые на них ссылаются.
Некоторые операции (например y.append(10) и y.sort()) изменяют объект, в то время, как внешне похожие операции (например y = y + [10] и sorted(y)) создают новый объект. Вообще в Python (и во всех случаях в стандартной библиотеке), метод, который изменяет объект, возвращает None, чтобы помочь избежать ошибок. Поэтому, если вы написали
думая, что это даст вам отсортированную копию y, вы вместо этого получите None, что скорее всего приведёт к легко диагностируемой ошибке.
Однако, существует один класс операций, где одна и та же операция ведёт себя по-разному с различными типами: расширенные операторы присваивания. Например, += изменяет списки, но не кортежи или числа (a_list += [1, 2, 3] эквивалентно a_list.extend([1, 2, 3])) и изменяет список, в то время, как some_tuple += (1, 2, 3) и some_int += 1 создают новый объект.
Если вы хотите знать, ссылаются ли 2 переменные на один объект или нет, вы можете использовать оператор is, или встроенную функцию id.
Как создавать функции более высокого порядка?
Есть два пути: использовать вложенные функции или вызываемые объекты. Например, с использованием вложенных функций:
Использование вызываемого объекта:
В обоих случаях,
даёт функцию, что (к примеру) taxes(10e6) == 0.3 * 10e6 + 2.
Использование вызываемого объекта - немного медленнее, и в результате получается больше кода. Однако, заметьте, что несколько функций могут разделять свою сигнатуру с помощью наследования:
Объект может сохранять свое состояние для нескольких вызовов:
Здесь inc, dec, reset выступают в роли функций, которые разделяют одну и ту же переменную.
Как скопировать объект в Python?
В общем случае, с помощью модуля copy.
Некоторые объекты можно скопировать более просто. Словари имеют метод copy:
Последовательности могут быть скопированы путём срезов:
dir(x) возвращает список методов и атрибутов.
Как можно узнать имя объекта?
Вообще говоря, никак, поскольку объекты в действительности не имеют имён. Важно: присваивание всегда связывает имя с объектом. Это верно и для инструкций def и class.
Возможно, класс имеет имя: однако, хотя он связан с двумя именами и запрашивается через имя B, созданный экземпляр всё ещё считается экземпляром класса A. Однако, невозможно сказать, имя экземпляра a или b, поскольку оба они связаны с одним и тем же значением.
Какой приоритет у оператора "запятая"?
Запятая не является оператором в Python.
Поскольку запятая - не оператор, но разделитель между выражениями, пример выше исполняется как если бы было введено:
А не
То же самое верно и для операторов присваивания (=, += и другие). Они не являются операторами как таковыми, а лишь синтаксическими разделителями в операциях присваивания.
Есть ли в Python эквивалент тернарного оператора "?:" в C?
Не пытайтесь это делать дома!
Почему -22 // 10 равно -3?
Поскольку i % j имеет тот же знак, что j. А ещё
Никак, поскольку строки неизменяемы. В большинстве ситуаций, нужно просто сделать новую строку из различных частей. Однако, если так нужно, можно использовать io.StringIO, либо модуль array:
Как использовать строки для вызова функций/методов?
Существует несколько приёмов.
- Лучший - использование словаря, ставящего соответствие строке функцию. Его главное достоинство - строки не обязаны совпадать с названиями функций.
Можно использовать S.rstrip("\r\n") для удаления символов новой строки, без удаления конечных пробелов:
Как удалить повторяющиеся элементы в списке?
Как создать многомерный список?
Возможно, вы попробуете этот неудачный вариант:
Это выглядит правильно, если напечатать:
Но если вы присвоите значение, то оно появится в нескольких местах:
Причина в том, что оператор * не создаёт копию, а только ссылку на существующий объект. *3 создаёт список из 3 ссылок на один и тот же список. Изменение в одной строке изменяют другие, что, вероятно, не то, что вы хотите.
Возможные пути решения:
Или, можно использовать специальные модули, предоставляющие матрицы. Наиболее известным является NumPy.
Почему a_tuple[i] += ['item'] не работает, а добавление работает?
Это из-за того, что расширенный оператор присваивания - оператор присваивания, а также из-за разницы между изменяемыми и неизменяемыми объектами в Python.
Это обсуждение относится в общем, когда расширенные операторы присваивания применяются к элементам кортежа, которые указывают на изменяемые объекты, но мы будем использовать список и +=, как образец.
Если вы напишете:
Причина исключения должна быть понятна: 1 добавляется к объекту a_tuple[0], но когда мы пытаемся присвоить результат, 2, к первому элементу в кортеже, мы получаем ошибку, поскольку мы не можем изменить элемент кортежа.
То есть, это выражение делает следующее:
Когда мы пишем что-то вроде:
Исключение немного более неожиданное, но более удивителен тот факт, что, несмотря на ошибку, элемент добавился!
Чтобы понять, что случилось, нужно знать, что:
- Если объект определяет метод __iadd__, он вызывается, когда выполняется +=, и возвращенное значение используется для присваивания
- Для списков, __iadd__ эквивалентен вызову extend для списка
__iadd__ завершился успешно, и список увеличился, но присваивание законилось ошибкой.
Для вставки кода на Python в комментарий заключайте его в теги
- Модуль csv - чтение и запись CSV файлов
- Создаём сайт на Django, используя хорошие практики. Часть 1: создаём проект
- Онлайн-обучение Python: сравнение популярных программ
- Книги о Python
- GUI (графический интерфейс пользователя)
- Курсы Python
- Модули
- Новости мира Python
- NumPy
- Обработка данных
- Основы программирования
- Примеры программ
- Типы данных в Python
- Видео
- Python для Web
- Работа для Python-программистов
- Сделай свой вклад в развитие сайта!
- Самоучитель Python
- Карта сайта
- Отзывы на книги по Python
- Реклама на сайте
Использование global в Python
Здравствуйте, знакомлюсь с python и после c++ категорически не понимаю принцип использования global переменных. Если у переменной, находящейся в def указать global то можно ли её значение использовать вне этой функции, у меня точно не получается. Может просто потому что я новичок и очевидные вещи для меня еще слишком сложны.
def check(): global urokb_in urokb_in = 1 with open('users.txt', 'r') as f: line = f.readline() f.close() with open('progress.txt', 'r') as k: while True: global uroka_in lines = k.readline() if line == lines.rstrip(): uroka_in = int(k.readline().rstrip()) urokb_in = uroka_in + 1 uroka_str = str(uroka_in) urokb_str = str(urokb_in) lines.replace(uroka_str, urokb_str) k.close() break if not lines: k.close() urokb_in = 1 with open('progress.txt', 'a') as j: j.write(line) j.write('\n') j.write(str(urokb_in)) j.write('\n') j.close() break if urokb_in == 1: educate__scr = PhotoImage(file='e_scr_1.png') educate_label = Label(root, image=educate__scr) educate_label.place(x=0, y=0)
Более опытные кодеры подскажите как исправить. SyntaxError: name 'urokb_in' is used prior to global declaration
Отслеживать
47.5k 17 17 золотых знаков 56 56 серебряных знаков 99 99 бронзовых знаков
задан 7 янв 2018 в 14:29
андрей гривкин андрей гривкин
353 1 1 золотой знак 5 5 серебряных знаков 12 12 бронзовых знаков
global uroka_in должно быть внутри функции (сразу после def , только один раз).
7 янв 2018 в 14:33
Возможный дубликат вопроса: Ошибка с переменной global?
7 янв 2018 в 14:38
@insolor тогда я не могу использовать значение urokb_in в условии вне функции
7 янв 2018 в 14:54
Можете. У вас просто функция не вызывается, насколько я понимаю. Нужно сначала вызвать функцию, а потом уже проверять условие.
7 янв 2018 в 14:56
@insolor def chek вызывается ранее по нажатию на кнопку. И при выходе из функции я хочу получить значение из urokb_in
7 янв 2018 в 14:59
4 ответа 4
Сортировка: Сброс на вариант по умолчанию
Если вы хотите новую глобальную переменную создать/или переопределить старую внутри функции (не на глобальном уровне), то можно global использовать. Это может быть полезно при работе с multiprocessing модулем, чтобы унаследовать желаемые глобальные переменные от родительского процесса:
def init(shared_arr_): global shared_arr shared_arr = shared_arr_ # must be inherited, not passed as an argument
Если вы хотите просто использовать существующую глобальную переменную, не переопределяя её, то global не нужен (иначе к примеру, пришлось бы в каждой функции каждый используемый модуль, каждую глобальную функцию объявлять global).
я новичок и очевидные вещи для меня еще слишком сложны
Для новичков: не переопределяйте глобальные переменные вообще, то есть избегайте global . Считайте каждое появление global в коде ошибкой, если нет особых причин для использования этой конструкции (как в примере с multiprocessing ). Если не получается избавится от global, то создайте минимальный пример кода и задайте отдельный вопрос: "как избавиться от global, делая X"
Отслеживать
ответ дан 7 янв 2018 в 17:18
52.2k 11 11 золотых знаков 108 108 серебряных знаков 311 311 бронзовых знаков
как локально присвоить глобальной переменной значение? у меня создавалась локальная переменная с тем же именем. ну кроме nonlocal =)
18 мар 2019 в 1:17
@eri посмотрите на shared_arr в примере кода выше. Какое поведение вы ожидали и что вместо этого происходит?
18 мар 2019 в 18:50
Инструкция global используется там где необходимо явно указать на то, что следует использовать объект из глобальной области видимости (namespace модуля или словарь globals) и отменяет стандартный механизм поиска для переменной ( LEGB ), дополнительно к этому даёт возможность изменения объекта не в своей области видимости. требует дисциплины в общем то, так как если до объявления global a во вложенной области видимости имени а не было в OВ globals() она будет создана при первой операции присваивания и не пропадёт при завершении работы (к примеру функции).
dir() # ['__builtins__'] def foo(): global a a = 22 pass dir() # ['__builtins__', 'foo'] # foo необходимо вызвать. foo() dir() # ['__builtins__', 'a', 'foo'] a # 22 # а теперь живет в globals() def foo1(): print(a) foo1() # 22 # по правилу LEGB имя а было найдено в globals() def foo2(): a += 4 pass foo2() # Traceback (most recent call last): # File "", line 1, in # File "", line 2, in foo2 # UnboundLocalError: local variable 'a' referenced before assignment # запрещено изменение переменных не в своей области видимости для этого # требуется сначала указать что нужно изменить именно a из globals() def foo3(): global a a += 4 foo3() a # 26
Локальные и глобальные переменные
В программировании особое внимание уделяется концепции о локальных и глобальных переменных, а также связанное с ними представление об областях видимости. Соответственно, локальные переменные видны только в локальной области видимости, которой может выступать отдельно взятая функция. Глобальные переменные видны во всей программе. "Видны" – значит, известны, доступны. К ним можно обратиться по имени и получить связанное с ними значение.
К глобальной переменной можно обратиться из локальной области видимости. К локальной переменной нельзя обратиться из глобальной области видимости, потому что локальная переменная существует только в момент выполнения тела функции. При выходе из нее, локальные переменные исчезают. Компьютерная память, которая под них отводилась, освобождается. Когда функция будет снова вызвана, локальные переменные будут созданы заново.
Вернемся к нашей программе из прошлого урока, немного упростив ее для удобства:
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
В этой статье мы рассмотрим как используется и для чего нужна глобальная переменная в Python.
Введение
Ключевое слово global в Python объявляет одну или несколько переменных глобальными. Этот оператор используется только в функциях.
По умолчанию переменные, объявленные в функции, являются локальными переменными, то есть доступ к ним возможен только в той функции, в которой они были созданы.
Использование локальных переменных
def hello_user(): name = "Egor" print(f"hello ") hello_user() print(f"hi ")
Выходные данные
hello Egor NameError: name 'name' is not defined
Пытаясь получить доступ к переменной, которая была создана внутри функции (локальная переменная) вне функции, вы получаете ошибку NameError, потому что эта переменная не известна в глобальной области видимости.
В программировании может потребоваться обращение к локальной переменной в глобальном масштабе, и это становится возможным в Python с помощью глобального оператора.
Глобальная переменная в функции
Для создания глобальной переменной в функции мы используем оператор global:
def hello_user(): global name name = "Egor" print(f"hello ") hello_user() print(f"hi ")
Выходные данные
hello Egor hi Egor
Обратите внимание, что без global name строка print(f»hi ») привела бы к ошибке.
Изменение глобальной переменной в функции
В Python по умолчанию можно получить доступ к глобальным переменным внутри функций, но не изменять их. Глобальный оператор делает работу, позволяя функциям модифицировать значения глобальных переменных в их локальной области видимости.
Пример попытки модификации глобальной переменной в функции:
a = 1 def plus_one(): a = a + 1 print(a) plus_one()
Выходные данные
UnboundLocalError: local variable 'a' referenced before assignment
Используемый оператор global для исправления ошибки доступа к переменной
a = 1 def plus_one(): global a a = a + 1 print(a) plus_one()
Выходные данные
Обратите внимание, что глобальная переменная a не создает новую глобальную переменную a, поскольку она уже существует. Она только предоставляет функции доступ к переменной a для модификации или использования.
Заключение
В данной статьи мы рассмотрели как используется и для чего нужна глобальная переменная в Python.