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


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

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


2416


источник


Ответы:


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

См. Другие ответы, если вы хотите поделиться глобальной переменной между модулями.


3444



Если я правильно понимаю вашу ситуацию, то, что вы видите, является результатом того, как 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 VM потребовалось бы выполнить по крайней мере три поиска имен каждый раз, когда новое имя назначается внутри функции (чтобы гарантировать, что имя didn ' t уже существуют на модуле / встроенном уровне), что значительно замедлит очень частое выполнение операции.)


655



Вы можете изучить понятие Пространства имен , В Python модуль является естественным местом для Глобальный данные:

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

Здесь описывается конкретное использование глобального модуля в-модуле - как-ду-я-шер-глобальные-переменные-через-модули , а для полноты содержание здесь делится:

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

174



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

Посмотрите, как baz, который появляется в левой части задания в foo(), единственный LOAD_FASTпеременная.


74



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

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

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


47



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

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

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

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


36



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

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

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!!!'

Модификация глобальной переменной изнутри функции

Чтобы указать глобальную переменную на другом объекте, вам нужно снова использовать глобальное ключевое слово:

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!!!'

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


31



With parallel execution, global variables can cause unexpected results if you don't understand what is happening. Here is an example of using a global variable within multiprocessing. We can clearly see that each process works with its own copy of the variable:

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

Output:

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]

28



You need to reference the global variable in every function you want to use.

As follows:

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

19