Usar variáveis globais numa função
Como posso criar ou usar uma variável global numa função?
Se eu criar uma variável global numa função, como posso usar essa variável global noutra função? Preciso armazenar a variável global em uma variável local da função que precisa de seu acesso?
18 answers
Você pode usar uma variável global noutras funções declarando-a como global
em cada função que lhe atribui:
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
Imagino que a razão para isso seja que, uma vez que as variáveis globais são tão perigosas, o Python quer certificar-se de que você realmente sabe que é com isso que está a jogar, exigindo explicitamente a palavra-chave global
.
Veja outras respostas se quiser partilhar uma variável global entre módulos.
Se eu estou entendendo a sua situação corretamente, o que você está vendo é o resultado de como Python lida com espaços de nomes locais (função) e globais (módulo).
Digamos que tens um módulo como este.# sample.py
myGlobal = 5
def func1():
myGlobal = 42
def func2():
print myGlobal
func1()
func2()
Pode esperar que isto publique 42, mas em vez disso imprime 5. Como já foi mencionado, se adicionar uma declaração 'global
' a func1()
, então func2()
irá imprimir 42.
def func1():
global myGlobal
myGlobal = 42
O que se passa aqui é que o Python assume que qualquer nome atribuído a para , em qualquer lugar dentro de uma função, é local para essa função, a menos que explicitamente dito o contrário. Se for apenas a ler a partir de um nome, e o nome não existir localmente, ele tentará procurar o nome em quaisquer âmbitos contendo (por exemplo, o escopo global do módulo).
Quando atribui 42 ao nome myGlobal
, Como tal, o Python cria uma variável local que esconde a variável global do mesmo nome. Esse local sai do âmbito e é recolhido do lixo quando func1()
devolve; entretanto, func2()
nunca poderá ver nada além do nome global (não modificado). Lembre-se que esta decisão do espaço de nomes acontece na hora de compilação, não na hora de execução -- se você tiver que ler o valor de myGlobal
dentro de func1()
antes de atribuir a ele, você terá um UnboundLocalError
, porque o Python já decidiu que deve ser uma variável local, mas ainda não tem nenhum valor associado a ela. Mas usando a Declaração ' global
', você diz ao Python que ele deve procurar em outro lugar o nome em vez de atribuindo-o localmente.
(eu acredito que esse comportamento originado em grande parte através de uma otimização do local de namespaces -- sem esse comportamento, Python VM seria necessário realizar, pelo menos, três pesquisas de nome cada vez que um novo nome seja atribuído para dentro de uma função (para garantir que o nome já não existe no módulo/builtin nível), o que poderia reduzir significativamente uma forma muito comum de operação.)
Você pode querer explorar a noção de espaços de nomes . Em Python, o módulo é o local natural para global Dados:
Cada módulo tem a sua própria tabela de símbolos privados, que é usada como a tabela de símbolos globais por todas as funções definidas no módulo. Assim, o autor de um módulo pode usar variáveis globais no módulo sem se preocupar com confrontos acidentais com variáveis globais de um usuário. Por outro lado, se você sabe o que está fazendo você pode tocar as variáveis globais de um módulo com a mesma notação usada para se referir às suas funções,
modname.itemname
.
Uma utilização específica do global-in-a-module é descrita aqui - how-do-i-share-global-variables-across-modules, e para completar o conteúdo é partilhado aqui:
A maneira canônica de compartilhar informações através de módulos dentro de um ÚNICO programa é criar um módulo de configuração especial (muitas vezes chamado de configuração ou cfg). Basta importar o módulo de configuração em todos os módulos de sua aplicação; o módulo então fica disponível como um nome global. Como há apenas uma instância de cada módulo, quaisquer mudanças feitas no objeto do módulo são refletidas em todos os lugares. Por exemplo:
Ficheiro: config.py
x = 0 # Default value of the 'x' configuration setting
Ficheiro: mod.py
import config
config.x = 1
Ficheiro: main.py
import config
import mod
print config.x
O Python usa uma heurística simples para decidir de que âmbito deve carregar uma variável, entre local e global. Se um nome de variável aparece no lado esquerdo de uma atribuição, mas não é declarado global, assume-se que é local. Se não aparecer no lado esquerdo de uma missão, presume-se que seja global.
>>> 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
>>>
Veja como baz, que aparece no lado esquerdo de uma atribuição em foo()
, é a única variável LOAD_FAST
.
Se quiser referir-se a uma variável global numa função, pode usar a palavra-chave global para declarar quais as variáveis que são globais. Você não tem que usá - lo em todos os casos (como alguém aqui afirma incorretamente) - se o nome referenciado em uma expressão não pode ser encontrado no escopo local ou âmbitos nas funções em que esta função é definida, ele é pesquisado entre as variáveis globais.
No entanto, se atribuir a uma nova variável não declarada como global na função, é implicitamente declarado como local, e pode ofuscar qualquer variável global existente com o mesmo nome.
Também, variáveis globais são úteis, ao contrário de alguns OOP zelotes que afirmam o contrário-especialmente para scripts menores, onde OOP é exagerado.
Além das respostas já existentes e para tornar isto mais confuso:
Em Python, as variáveis que só são referenciadas dentro de uma função são: Implicitamente global . Se for atribuído a uma variável um novo valor em qualquer lugar dentro do corpo da função, assume-se que é um local. Se for uma variável é sempre atribuído um novo valor dentro da função, a variável é implicitamente local, e você precisa declará-lo explicitamente como "global".
Mas um pouco. surpreendente no início, um momento de consideração explica presente. Por um lado, a exigência de um valor global para as variáveis atribuídas fornece uma barra contra efeitos secundários não intencionais. Por outro lado, se a global necessário para todas as referências globais, você estaria usando global todos os tempo. Você teria que declarar como global todas as referências a um embutido função ou a um componente de um módulo importado. Esta confusão derrota a utilidade da declaração global para identificar secundario.
Fonte: quais são as regras para variáveis locais e globais em Python?.
Se eu criar uma variável global numa função, como posso usar essa variável noutra função?
Podemos criar um global com a seguinte função:
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'
Escrever uma função não executa o seu código. Então chamamos a função create_global_variable
:
>>> create_global_variable()
Usando globais sem modificação
Podes usá-lo, desde que não esperes mudar para que objecto aponta:
Por exemplo,
def use_global_variable():
return global_variable + '!!!'
E agora podemos usar a variável global:
>>> use_global_variable()
'Foo!!!'
Modificação da variável global a partir do interior de uma função
Para apontar a variável global para um objecto diferente, é necessário usar a palavra-chave global de novo:
def change_global_variable():
global global_variable
global_variable = 'Bar'
Note que depois de escrever esta função, o código que a alterou ainda não funcionou:
>>> use_global_variable()
'Foo!!!'
Então depois de chamar a função:
>>> change_global_variable()
Podemos ver que a variável global foi alterada. O global_variable
o nome agora aponta para 'Bar'
:
>>> use_global_variable()
'Bar!!!'
Note que "global" em Python não é verdadeiramente global - é apenas global ao nível dos módulos. Portanto, só está disponível para funções escritas nos módulos em que é global. As funções recordam o módulo em que são escritas, por isso, quando são exportadas para outros módulos, continuam a procurar no módulo em que foram criadas para encontrar variáveis globais.
Variáveis locais com o mesmo nome
Se criar uma variável local com o mesmo nome, irá ofuscar uma variável global:
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!!!'
Mas usar essa variável local mal nominada não altera a variável global:
>>> use_global_variable()
'Bar!!!'
Note que você deve evitar usar as variáveis locais com os mesmos nomes que os globais, a menos que você saiba exatamente o que está fazendo e tenha uma boa razão para fazê-lo. Ainda não encontrei essa razão.
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))
Resultado:
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]
É necessário referenciar a variável global em todas as funções que deseja usar.
Como se segue:
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]
"""
O que estás a dizer é para usar o método assim:
globvar = 5
def f():
var = globvar
print(var)
f() # Prints 5
Mas a melhor maneira é usar a variável global como esta:
globavar = 5
def f():
global globvar
print(globvar)
f() #prints 5
Ambos dão a mesma saída.
Aqui está um pequeno módulo de amostra com uma forma simples de o mostrar numa definição main
:
def five(enterAnumber,sumation):
global helper
helper = enterAnumber + sumation
def isTheNumber():
return helper
Aqui está como mostrá-lo em uma definição main
:
import TestPy
def main():
atest = TestPy
atest.five(5,8)
print(atest.isTheNumber())
if __name__ == '__main__':
main()
Este código simples funciona assim e vai ser executado. Espero que ajude.
Você não está realmente armazenando o global em uma variável local, apenas criando uma referência local ao mesmo objeto a que sua referência global original se refere. Lembre-se que praticamente tudo em Python é um nome que se refere a um objeto, e nada é copiado na operação habitual.
Se não tiver de especificar explicitamente quando um identificador se refere a um global predefinido, então terá de indicar explicitamente quando um identificador é uma nova variável local em vez disso (por exemplo, com algo como o comando 'var' visto em JavaScript). Uma vez que as variáveis locais são mais comuns do que as variáveis globais em qualquer sistema sério e não trivial, o sistema de Python faz mais sentido na maioria dos casos.
Você poderia ter uma linguagem que tentasse adivinhar, usando uma variável global se existisse ou criando uma variável local se não existisse. no entanto, isso seria muito propenso a erros. Por exemplo, importar outro módulo poderia inadvertidamente introduzir um variável global com esse nome, mudando o comportamento de seu programa.
Tenta isto:
def x1():
global x
x = 6
def x2():
global x
x = x+1
print x
x = 5
x1()
x2() # output --> 7
A seguir e como um add on, use um ficheiro para conter todas as variáveis globais declaradas localmente e depois 'importar como':
Ficheiro initval.py
Stocksin = 300
Prices = []
Ficheiro getstocks.py
import initval as iv
Def getmystocks ():
iv.Stocksin = getstockcount ()
Def getmycharts ():
For ic in range (0,iv.Stocksin):
.....
Escrever a elementos explícitos de uma matriz global aparentemente não precisa da declaração global, embora escrever-lhe "grossista" tenha esse requisito:
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
No caso de ter uma variável local com o mesmo nome, poderá querer usar o globals()
Função
globals()['your_global_var'] = 42
Consulte o espaço de nomes da classe onde quer que a mudança apareça.
Neste exemplo, o runner está a usar max da configuração do ficheiro. Quero que o meu teste altere o valor de max quando o runner o estiver a usar.
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()
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
E
from pickle import dump
def dumpfile(name):
with open(name+".dat", "wb") as outfile:
dump(globals()[name], outfile)
return True
Vai deixar-te descarregar / carregar variáveis de e para o espaço de nomes global. Muito conveniente, sem confusões, sem problemas. Tenho a certeza que é só python 3.