Использование глобальных переменных в функции

Как создать или использовать глобальную переменную в функции?

Если я создаю глобальную переменную в одной функции, как я могу использовать эту глобальную переменную в другой функции? Нужно ли хранить глобальную переменную в локальной переменной функции, которая нуждается в ее доступе?

18 ответов


вы можете использовать глобальную переменную в других функциях, объявив ее как 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. Как уже упоминалось, если вы добавите' до 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 описано здесь -how-do-i-share-global-переменные через модули, а для полноты содержания делятся здесь:

канонический способ обмена информацией между модулями в рамках одной программы-создать специальный модуль (часто называемый 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 переменной.


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

однако, если вы назначаете новой переменной, не объявленной как глобальная в функция, она неявно объявлена как локальная и может затенять любую существующую глобальную переменную с тем же именем.

кроме того, глобальные переменные полезны, в отличие от некоторых фанатиков ООП, которые утверждают обратное - особенно для небольших скриптов, где ООП является излишним.


В дополнение к уже существующим ответам и сделать это более запутанной:

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

хотя немного удивительно сначала, момент рассмотрения объясняет этот. С одной стороны, требование global для назначенных переменных обеспечивает бар против непреднамеренных побочных эффектов. С другой стороны, если глобальный требуется для всех глобальных ссылок, вы будете использовать global all the время. Вы должны были бы объявить как глобальный каждую ссылку на встроенный функция или к компоненту импортированного модуля. Этот беспорядок свести на нет полезность глобальной декларации для идентифицирующий побочные явления.

источник: каковы правила для локальных и глобальных переменных в Python?.


если я создаю глобальную переменную в одной функции, как я могу использовать эту переменную в другую функцию?

мы можем создать глобальный со следующей функцией:

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()

мы видим, что глобальная переменная была изменена. The 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!!!'

обратите внимание, что вы должны избегать использования локальных переменных с теми же именами, что и глобалы, если вы точно не знаете, что делаете, и у вас есть для этого очень веская причина. У меня есть еще не сталкивался с такой причиной.


при параллельном выполнении глобальные переменные могут вызвать неожиданные результаты, если вы не понимаете, что происходит. Вот пример использования глобальной переменной в многопроцессорной обработке. Мы ясно видим, что каждый процесс работает со своей копией переменной:

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]

вам нужно ссылаться на глобальную переменную в каждой функции, которую вы хотите использовать.

следующим образом:

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]
"""

то, что вы говорите, - это использовать такой метод:

globvar = 5

def f():
    var = globvar
    print(var)

f()  # Prints 5

но лучший способ-использовать глобальную переменную следующим образом:

globavar = 5
def f():
    global globvar
    print(globvar)
f()   #prints 5

оба дают одинаковый выход.


как выясняется, ответ всегда прост.

вот небольшой образец модуля с простым способом показать его в 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()

этот простой код работает именно так, и он будет выполняться. Надеюсь, это поможет.


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

Если вам не нужно было явно указывать, когда идентификатор должен ссылаться на предопределенную глобальную, то вам, вероятно, придется явно указать, когда идентификатор является новой локальной переменной вместо этого (например, с чем-то вроде команды "var", увиденной в JavaScript). Поскольку локальные переменные более распространены, чем глобальные переменные в любой серьезной и нетривиальной системе, Система Python имеет больше смысла в большинстве случаев.

вы мог бы есть язык, который пытался угадать, используя глобальную переменную, если она существует, или создавая локальную переменную, если она не существует. Тем не менее, это было бы очень подвержено ошибкам. Например, импорт другого модуля может произойти непреднамеренно введите глобальную переменную с этим именем, изменив поведение вашей программы.


попробуйте это:

def x1():
    global x
    x = 6

def x2():
    global x
    x = x+1
    print x

x = 5
x1()
x2()  # output --> 7

после и в качестве дополнения используйте файл, содержащий все глобальные переменные, объявленные локально, а затем "импортировать как":

файл 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() функции.

globals()['your_global_var'] = 42

ссылка на пространство имен класса, где вы хотите изменить, чтобы показать.

в этом примере runner использует Макс из файла config. Я хочу, чтобы мой тест изменил значение Макс когда runner использует его.

main/config.py

max = 15000

main/runner.py

from main import config
def check_threads():
    return max < thread_count 

tests/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()

Я добавляю это, как я не видел его ни в одном из других ответов и это может быть полезно для кого-то борется с чем-то подобным. Функция 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 только.