Использование глобальных переменных в функции - PullRequest
2807 голосов
/ 08 января 2009

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

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

Ответы [ 18 ]

3886 голосов
/ 08 января 2009

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

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

722 голосов
/ 08 января 2009

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

198 голосов
/ 08 января 2009

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

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

Здесь описывается конкретное использование global-in-a-module - Как мне совместно использовать глобальные переменные между модулями? , а для полноты содержания здесь:

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

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 переменной.

54 голосов
/ 08 января 2009

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

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

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

42 голосов
/ 04 июля 2014

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

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

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

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

37 голосов
/ 01 января 2016

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

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

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

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

31 голосов
/ 03 октября 2013

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

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]
22 голосов
/ 13 октября 2013

Как оказалось, ответ всегда прост.

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

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

21 голосов
/ 04 декабря 2014

То, что вы говорите, это использовать метод, подобный этому:

globvar = 5

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

f()  # Prints 5

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

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

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

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