Использование глобальных переменных в функции
Как я могу создать или использовать глобальную переменную в функции?
Если я создаю глобальную переменную в одной функции, как я могу использовать эту глобальную переменную в другой функции? Нужно ли хранить глобальную переменную в локальной переменной функции, которой нужен доступ?
25 ответов
Вы можете использовать глобальную переменную в других функциях, объявив ее как global
в каждой функции, которая ему присваивается:
globvar = 0
def set_globvar_to_one():
global globvar # Needed to modify global copy of globvar
globvar = 1
def print_globvar():
print(globvar) # No need for global declaration to read value of globvar
set_globvar_to_one()
print_globvar() # Prints 1
Я предполагаю, что причина в том, что, поскольку глобальные переменные настолько опасны, Python хочет убедиться, что вы действительно знаете, с чем вы играете, явно требуя global
ключевое слово.
Смотрите другие ответы, если вы хотите поделиться глобальной переменной между модулями.
Если я правильно понимаю вашу ситуацию, то, что вы видите, является результатом того, как Python обрабатывает локальные (функциональные) и глобальные (модульные) пространства имен.
Скажем, у вас есть такой модуль:
# sample.py
myGlobal = 5
def func1():
myGlobal = 42
def func2():
print myGlobal
func1()
func2()
Вы можете ожидать, что это напечатает 42, но вместо этого он печатает 5. Как уже упоминалось, если вы добавите 'global
объявление func1()
, затем func2()
напечатает 42.
def func1():
global myGlobal
myGlobal = 42
Здесь происходит то, что Python предполагает, что любое имя, которое присваивается в любом месте функции, является локальным для этой функции, если явно не указано иное. Если это только чтение из имени, а имя не существует локально, оно попытается найти имя в любой содержащей области (например, в глобальной области видимости модуля).
Когда вы назначаете 42 имени myGlobal
поэтому Python создает локальную переменную, которая скрывает глобальную переменную с тем же именем. Этот локальный выходит из области видимости и собирает мусор, когда func1()
возвращается; Между тем, func2()
никогда не увидит ничего, кроме (неизмененного) глобального имени. Обратите внимание, что это решение пространства имен происходит во время компиляции, а не во время выполнения - если вы должны были прочитать значение myGlobal
внутри func1()
прежде чем назначить на него, вы получите UnboundLocalError
потому что Python уже решил, что это должна быть локальная переменная, но у него еще не было никакого значения, связанного с ней. Но с помощьюglobal
"Вы говорите Python, что он должен искать имя в другом месте, а не присваивать его локально.
(Я полагаю, что такое поведение возникло в основном за счет оптимизации локальных пространств имен - без этого поведения виртуальная машина Python должна была бы выполнять как минимум три поиска имен каждый раз, когда новое имя назначается внутри функции (чтобы гарантировать, что имя не уже существует на уровне модуля / встроенного), что значительно замедлит очень распространенную операцию.)
Вы можете изучить понятие пространств имен. В Python модуль является естественным местом для глобальных данных:
Каждый модуль имеет свою собственную таблицу частных символов, которая используется в качестве глобальной таблицы символов всеми функциями, определенными в модуле. Таким образом, автор модуля может использовать глобальные переменные в модуле, не беспокоясь о случайных столкновениях с глобальными переменными пользователя. С другой стороны, если вы знаете, что делаете, вы можете прикоснуться к глобальным переменным модуля, используя те же обозначения, что и для ссылок на его функции,
modname.itemname
,
Конкретное использование global-in-a-module описано здесь - http://effbot.org/pyfaq/how-do-i-share-global-variables-across-modules.htm, а для полноты содержания здесь представлено:
Канонический способ обмена информацией между модулями в рамках одной программы заключается в создании специального модуля конфигурации (часто называемого config или cfg). Просто импортируйте модуль конфигурации во все модули вашего приложения; модуль становится доступным как глобальное имя. Поскольку существует только один экземпляр каждого модуля, любые изменения, внесенные в объект модуля, отражаются повсеместно. Например:
Файл: config.py
x = 0 # Default value of the 'x' configuration setting
Файл: mod.py
import config
config.x = 1
Файл: main.py
import config
import mod
print config.x
Python использует простую эвристику, чтобы решить, из какой области он должен загружать переменную, между локальной и глобальной. Если имя переменной появляется в левой части присваивания, но не объявлено как глобальное, оно считается локальным. Если он не отображается слева от присвоения, он считается глобальным.
>>> import dis
>>> def foo():
... global bar
... baz = 5
... print bar
... print baz
... print quux
...
>>> dis.disassemble(foo.func_code)
3 0 LOAD_CONST 1 (5)
3 STORE_FAST 0 (baz)
4 6 LOAD_GLOBAL 0 (bar)
9 PRINT_ITEM
10 PRINT_NEWLINE
5 11 LOAD_FAST 0 (baz)
14 PRINT_ITEM
15 PRINT_NEWLINE
6 16 LOAD_GLOBAL 1 (quux)
19 PRINT_ITEM
20 PRINT_NEWLINE
21 LOAD_CONST 0 (None)
24 RETURN_VALUE
>>>
Посмотрите, как баз, который появляется на левой стороне задания в foo()
, единственный LOAD_FAST
переменная.
Если вы хотите сослаться на глобальную переменную в функции, вы можете использовать ключевое слово global, чтобы объявить, какие переменные являются глобальными. Вам не нужно использовать его во всех случаях (как здесь неправильно утверждают) - если имя, на которое есть ссылка в выражении, не может быть найдено в локальной области видимости или области действия в функциях, в которых определена эта функция, оно ищется среди глобальных переменные.
Однако если вы присваиваете новую переменную, не объявленную как глобальную в функции, она неявно объявляется как локальная, и она может затмить любую существующую глобальную переменную с тем же именем.
Кроме того, глобальные переменные полезны, в отличие от некоторых фанатиков ООП, которые утверждают иначе - особенно для небольших сценариев, где ООП является избыточным.
Если я создаю глобальную переменную в одной функции, как я могу использовать эту переменную в другой функции?
Мы можем создать глобал с помощью следующей функции:
def create_global_variable():
global global_variable # must declare it to be a global first
# modifications are thus reflected on the module's global scope
global_variable = 'Foo'
Написание функции фактически не запускает ее код. Итак, мы называем create_global_variable
функция:
>>> create_global_variable()
Использование глобалов без изменений
Вы можете просто использовать его, если вы не собираетесь изменять, на какой объект он указывает:
Например,
def use_global_variable():
return global_variable + '!!!'
и теперь мы можем использовать глобальную переменную:
>>> use_global_variable()
'Foo!!!'
Модификация глобальной переменной изнутри функции
Чтобы указать глобальную переменную на другой объект, необходимо снова использовать ключевое слово global:
def change_global_variable():
global global_variable
global_variable = 'Bar'
Обратите внимание, что после написания этой функции код, фактически изменяющий ее, все еще не выполняется:
>>> use_global_variable()
'Foo!!!'
Итак, после вызова функции:
>>> change_global_variable()
мы можем видеть, что глобальная переменная была изменена. global_variable
имя теперь указывает на 'Bar'
:
>>> use_global_variable()
'Bar!!!'
Обратите внимание, что "глобальный" в Python не является действительно глобальным - он только глобален для уровня модуля. Таким образом, он доступен только для функций, написанных в модулях, в которых он является глобальным. Функции запоминают модуль, в котором они написаны, поэтому, когда они экспортируются в другие модули, они все равно ищут модуль, в котором они были созданы, чтобы найти глобальные переменные.
Локальные переменные с тем же именем
Если вы создадите локальную переменную с тем же именем, она заменит глобальную переменную:
def use_local_with_same_name_as_global():
# bad name for a local variable, though.
global_variable = 'Baz'
return global_variable + '!!!'
>>> use_local_with_same_name_as_global()
'Baz!!!'
Но использование этой неправильно названной локальной переменной не меняет глобальную переменную:
>>> use_global_variable()
'Bar!!!'
Обратите внимание, что вам следует избегать использования локальных переменных с такими же именами, как у глобальных, если вы точно не знаете, что делаете, и у вас есть веская причина для этого. Я еще не сталкивался с такой причиной.
В дополнение к уже существующим ответам и чтобы сделать это более запутанным:
В Python переменные, на которые ссылаются только внутри функции, неявно глобальны. Если переменной в любом месте внутри тела функции назначается новое значение, оно считается локальным. Если переменной когда-либо присваивается новое значение внутри функции, переменная неявно является локальной, и вам необходимо явно объявить ее как "глобальную".
Хотя поначалу это немного удивляет, обдумывание этого объясняется моментом. С одной стороны, требование наличия глобальных для назначенных переменных обеспечивает защиту от непреднамеренных побочных эффектов. С другой стороны, если глобальный требовался для всех глобальных ссылок, вы бы использовали глобальный все время. Вы должны будете объявить как глобальные все ссылки на встроенную функцию или компонент импортируемого модуля. Этот беспорядок отрицает полезность глобальной декларации для выявления побочных эффектов.
Источник: Каковы правила для локальных и глобальных переменных в Python?,
При параллельном выполнении глобальные переменные могут привести к неожиданным результатам, если вы не понимаете, что происходит. Вот пример использования глобальной переменной в многопроцессорной среде. Мы ясно видим, что каждый процесс работает со своей собственной копией переменной:
import multiprocessing
import os
import random
import sys
import time
def worker(new_value):
old_value = get_value()
set_value(random.randint(1, 99))
print('pid=[{pid}] '
'old_value=[{old_value:2}] '
'new_value=[{new_value:2}] '
'get_value=[{get_value:2}]'.format(
pid=str(os.getpid()),
old_value=old_value,
new_value=new_value,
get_value=get_value()))
def get_value():
global global_variable
return global_variable
def set_value(new_value):
global global_variable
global_variable = new_value
global_variable = -1
print('before set_value(), get_value() = [%s]' % get_value())
set_value(new_value=-2)
print('after set_value(), get_value() = [%s]' % get_value())
processPool = multiprocessing.Pool(processes=5)
processPool.map(func=worker, iterable=range(15))
Выход:
before set_value(), get_value() = [-1]
after set_value(), get_value() = [-2]
pid=[53970] old_value=[-2] new_value=[ 0] get_value=[23]
pid=[53971] old_value=[-2] new_value=[ 1] get_value=[42]
pid=[53970] old_value=[23] new_value=[ 4] get_value=[50]
pid=[53970] old_value=[50] new_value=[ 6] get_value=[14]
pid=[53971] old_value=[42] new_value=[ 5] get_value=[31]
pid=[53972] old_value=[-2] new_value=[ 2] get_value=[44]
pid=[53973] old_value=[-2] new_value=[ 3] get_value=[94]
pid=[53970] old_value=[14] new_value=[ 7] get_value=[21]
pid=[53971] old_value=[31] new_value=[ 8] get_value=[34]
pid=[53972] old_value=[44] new_value=[ 9] get_value=[59]
pid=[53973] old_value=[94] new_value=[10] get_value=[87]
pid=[53970] old_value=[21] new_value=[11] get_value=[21]
pid=[53971] old_value=[34] new_value=[12] get_value=[82]
pid=[53972] old_value=[59] new_value=[13] get_value=[ 4]
pid=[53973] old_value=[87] new_value=[14] get_value=[70]
Как оказалось, ответ всегда прост.
Вот небольшой пример модуля с простым способом показать его в main
определение:
def five(enterAnumber,sumation):
global helper
helper = enterAnumber + sumation
def isTheNumber():
return helper
Вот как это показать в main
определение:
import TestPy
def main():
atest = TestPy
atest.five(5,8)
print(atest.isTheNumber())
if __name__ == '__main__':
main()
Этот простой код работает так же, и он будет выполняться. Я надеюсь, что это помогает.
То, что вы говорите, это использовать метод следующим образом:
globvar = 5
def f():
var = globvar
print(var)
f() # Prints 5
Но лучше всего использовать глобальную переменную следующим образом:
globavar = 5
def f():
global globvar
print(globvar)
f() #prints 5
Оба дают одинаковый результат.
Вам нужно ссылаться на глобальную переменную в каждой функции, которую вы хотите использовать.
Следующее:
var = "test"
def printGlobalText():
global var #wWe are telling to explicitly use the global version
var = "global from printGlobalText fun."
print "var from printGlobalText: " + var
def printLocalText():
#We are NOT telling to explicitly use the global version, so we are creating a local variable
var = "local version from printLocalText fun"
print "var from printLocalText: " + var
printGlobalText()
printLocalText()
"""
Output Result:
var from printGlobalText: global from printGlobalText fun.
var from printLocalText: local version from printLocalText
[Finished in 0.1s]
"""
Попробуй это:
def x1():
global x
x = 6
def x2():
global x
x = x+1
print x
x = 5
x1()
x2() # output --> 7
Вы на самом деле не храните глобальную переменную в локальной переменной, а просто создаете локальную ссылку на тот же объект, на который ссылается ваша исходная глобальная ссылка. Помните, что почти все в Python является именем, относящимся к объекту, и ничего не копируется в обычной операции.
Если вам не нужно было явно указывать, когда идентификатор должен был ссылаться на предопределенную глобальную переменную, вам, вероятно, придется явно указывать, когда вместо этого идентификатор является новой локальной переменной (например, с чем-то вроде команды 'var'). видел в JavaScript). Поскольку локальные переменные встречаются чаще, чем глобальные переменные в любой серьезной и нетривиальной системе, система Python в большинстве случаев имеет больше смысла.
У вас может быть язык, который пытается угадать, используя глобальную переменную, если она существует, или создавая локальную переменную, если она не существует. Однако это было бы очень подвержено ошибкам. Например, импорт другого модуля может непреднамеренно ввести глобальную переменную с таким именем, что приведет к изменению поведения вашей программы.
Если у вас есть локальная переменная с тем же именем, вы можете использовать globals()
функция
globals()['your_global_var'] = 42
В качестве дополнения используйте файл, содержащий все глобальные переменные, объявленные локально, а затем "импортируйте как":
Файл initval.py
Stocksin = 300
Prices = []
Файл getstocks.py
import initval as iv
Def getmystocks ():
iv.Stocksin = getstockcount ()
Def getmycharts ():
For ic in range (0,iv.Stocksin):
.....
Запись в явные элементы глобального массива, по-видимому, не нуждается в глобальном объявлении, хотя запись в него "оптовым" действительно имеет это требование:
import numpy as np
hostValue = 3.14159
hostArray = np.array([2., 3.])
hostMatrix = np.array([[1.0, 0.0],[ 0.0, 1.0]])
def func1():
global hostValue # mandatory, else local.
hostValue = 2.0
def func2():
global hostValue # mandatory, else UnboundLocalError.
hostValue += 1.0
def func3():
global hostArray # mandatory, else local.
hostArray = np.array([14., 15.])
def func4(): # no need for globals
hostArray[0] = 123.4
def func5(): # no need for globals
hostArray[1] += 1.0
def func6(): # no need for globals
hostMatrix[1][1] = 12.
def func7(): # no need for globals
hostMatrix[0][0] += 0.33
func1()
print "After func1(), hostValue = ", hostValue
func2()
print "After func2(), hostValue = ", hostValue
func3()
print "After func3(), hostArray = ", hostArray
func4()
print "After func4(), hostArray = ", hostArray
func5()
print "After func5(), hostArray = ", hostArray
func6()
print "After func6(), hostMatrix = \n", hostMatrix
func7()
print "After func7(), hostMatrix = \n", hostMatrix
Я добавляю это, поскольку я не видел это ни в одном из других ответов, и это могло бы быть полезным для кого-то, борющегося с чем-то подобным. Функция globals() возвращает изменяемый словарь глобальных символов, в котором вы можете "волшебным образом" сделать данные доступными для остальной части вашего кода. Например:
from pickle import load
def loaditem(name):
with open(r"C:\pickle\file\location"+"\{}.dat".format(name), "rb") as openfile:
globals()[name] = load(openfile)
return True
а также
from pickle import dump
def dumpfile(name):
with open(name+".dat", "wb") as outfile:
dump(globals()[name], outfile)
return True
Просто позволит вам выгружать / загружать переменные из и в глобальное пространство имен. Супер удобно, без суеты, без суеты. Я уверен, что это только Python 3.
global_var = 10 # will be considered as a global variable
def func_1():
global global_var # access variable using variable keyword
global_var += 1
def func_2():
global global_var
global_var *= 2
print(f"func_2: {global_var}")
func_1()
func_2()
print("Global scope:", global_var) # will print 22
Объяснение:
является глобальной переменной, и все функции и классы могут получить доступ к этой переменной.
В
func_1()
доступ к этой глобальной переменной с помощью ключевого слова
global
который указывает на переменную, которая записана в глобальной области видимости. Если бы я не написал ключевое слово global, переменная внутри считалась бы локальной переменной, которую можно использовать только внутри функции. Затем внутри я увеличил эту глобальную переменную на 1.
То же самое произошло в
func_2()
.
После звонка
func_1
а также
func_2
, вы увидите
global_var
изменен
Глобалы в порядке - кроме многопроцессорной обработки
Глобалы в связи с многопроцессорностью на разных платформах / средах, таких как Windows/Mac OS с одной стороны и Linux с другой, вызывают проблемы.
Я покажу вам это на простом примере, указав на проблему, с которой я столкнулся некоторое время назад.
Если вы хотите понять, почему в Windows / MacO и Linux все по-другому, вам нужно знать, что механизм по умолчанию для запуска нового процесса на...
- Windows / MacOs - это спавн
- Linux - это вилка
Они разные в распределении памяти и инициализации... (но я не буду здесь вдаваться в подробности).
Давайте посмотрим на проблему / пример...
import multiprocessing
counter = 0
def do(task_id):
global counter
counter +=1
print(f'task {task_id}: counter = {counter}')
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=4)
task_ids = list(range(4))
pool.map(do, task_ids)
Windows
Если вы запустите это в Windows (и, я полагаю, в MacOS тоже), вы получите следующий результат...
task 0: counter = 1
task 1: counter = 2
task 2: counter = 3
task 3: counter = 4
Linux
Если вы запустите это в Linux, вы получите следующее.
task 0: counter = 1
task 1: counter = 1
task 2: counter = 1
task 3: counter = 1
Ссылка на пространство имен класса, где вы хотите, чтобы изменение отображалось.
В этом примере бегун использует max из файла config. Я хочу, чтобы мой тест изменил значение max, когда бегун его использует.
Основной /config.py
max = 15000
Основной /runner.py
from main import config
def check_threads():
return max < thread_count
Тесты /runner_test.py
from main import runner # <----- 1. add file
from main.runner import check_threads
class RunnerTest(unittest):
def test_threads(self):
runner.max = 0 # <----- 2. set global
check_threads()
Есть 2 способа объявить переменную глобальной:
1. назначить переменную внутри функций и использовать глобальную строку
def declare_a_global_variable():
global global_variable_1
global_variable_1 = 1
# Note to use the function to global variables
declare_a_global_variable()
2. назначить переменную вне функций:
global_variable_2 = 2
Теперь мы можем использовать эти объявленные глобальные переменные в других функциях:
def declare_a_global_variable():
global global_variable_1
global_variable_1 = 1
# Note to use the function to global variables
declare_a_global_variable()
global_variable_2 = 2
def print_variables():
print(global_variable_1)
print(global_variable_2)
print_variables() # prints 1 & 2
Примечание 1:
Если вы хотите изменить глобальную переменную внутри другой функции, например update_variables()
вы должны использовать глобальную строку в этой функции перед назначением переменной:
global_variable_1 = 1
global_variable_2 = 2
def update_variables():
global global_variable_1, global_variable_2
global_variable_1 = 11
global_variable_2 = 12 # will update just locally for this function
print(global_variable_1) # prints 11
print(global_variable_2) # prints 2
Заметка 2:
Существует исключение для примечания 1 для переменных списка и словаря без использования глобальной строки внутри функции:
# declaring some global variables
variable = 'peter'
list_variable_1 = ['a','b']
list_variable_2 = ['c','d']
def update_global_variables():
"""without using global line"""
variable = 'PETER' # won't update in global scope
list_variable_1 = ['A','B'] # won't update in global scope
list_variable_2[0] = 'C' # updated in global scope surprisingly this way
list_variable_2[1] = 'D' # updated in global scope surprisingly this way
update_global_variables()
print('variable is: %s'%variable) # prints peter
print('list_variable_1 is: %s'%list_variable_1) # prints ['a', 'b']
print('list_variable_2 is: %s'%list_variable_2) # prints ['C', 'D']
Хотя на этот вопрос был дан ответ, я снова предлагаю решение, так как я предпочитаю одну строку Это если вы хотите создать глобальную переменную внутри функции
def someFunc():
x=20
globals()['y']=50
someFunc() # invoking function so that variable Y is created globally
print(y) # output 50
print(x) #NameError: name 'x' is not defined as x was defined locally within function
Как этот код:
myVar = 12
def myFunc():
myVar += 12
Ключ:
Если вы объявляете переменную вне строк, она становится глобальной.
Если вы объявляете переменную внутри строк, она становится локальной.
Если вы хотите объявить глобальную переменную внутри строк, используйте ключевое слово
global
перед переменной, которую вы хотите объявить:
myVar = 124
def myFunc():
global myVar2
myVar2 = 100
myFunc()
print(myVar2)
и тогда у вас есть 100 в документе.
Initialized = 0 #Here This Initialized is global variable
def Initialize():
print("Initialized!")
Initialized = 1 #This is local variable and assigning 1 to local variable
while Initialized == 0:
Здесь мы сравниваем глобальную переменную Initialized с 0, поэтому условие цикла выполняется
Initialize()
Функция будет вызвана. Цикл будет бесконечным
#if we do Initialized=1 then loop will terminate
else:
print("Lets do something else now!")
если вы хотите получить доступ к глобальной переменной, вы просто добавляете ключевое слово global внутри своей функции, например: global_var = 'yeah'
def someFunc():
global global_var;
print(nam_of_var)