Respostas:
Você pode usar uma variável global em outras 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 disso é que, como as variáveis globais são tão perigosas, o Python quer ter certeza de que você realmente sabe o que está brincando ao exigir explicitamente a global
palavra - chave.
Veja outras respostas se desejar compartilhar uma variável global entre módulos.
global
palavra-chave seja porque os globais são perigosos. Pelo contrário, é porque o idioma não exige que você declare explicitamente variáveis e assume automaticamente que uma variável que você atribui tem escopo de função, a menos que você diga o contrário. A global
palavra-chave é o meio fornecido para dizer o contrário.
f2()
estado mudança agora f3()
poderia fazer algo inesperado As funções podem agora operar agnóstico para o estado programa externo?.
Se estou entendendo sua situação corretamente, o que você está vendo é o resultado de como o Python lida com namespaces locais (funções) e globais (módulos).
Digamos que você tenha um módulo como este:
# sample.py
myGlobal = 5
def func1():
myGlobal = 42
def func2():
print myGlobal
func1()
func2()
Você pode esperar que isso imprima 42, mas em vez disso imprime 5. Como já foi mencionado, se você adicionar uma global
declaração ' ' a func1()
, func2()
imprimirá 42.
def func1():
global myGlobal
myGlobal = 42
O que está acontecendo aqui é que o Python assume que qualquer nome atribuído , em qualquer lugar de uma função, é local para essa função, a menos que seja explicitamente dito o contrário. Se estiver apenas lendo um nome e o nome não existir localmente, ele tentará procurar o nome em qualquer escopo que contenha (por exemplo, o escopo global do módulo).
Quando você atribui 42 ao nome myGlobal
, o Python cria uma variável local que oculta a variável global com o mesmo nome. Esse local sai do escopo e é coletado como lixo quando func1()
retorna; enquanto isso, func2()
nunca poderá ver nada além do nome global (não modificado). Observe que essa decisão de namespace ocorre no tempo de compilação, não no tempo de execução - se você lesse o valor de myGlobal
inside func1()
antes de atribuir a ele, obteria um UnboundLocalError
, porque o Python já decidiu que deve ser uma variável local, mas ainda não teve nenhum valor associado a ele. Mas, usando a global
instrução ' ', você diz ao Python que ele deve procurar o nome em outro lugar, em vez de atribuí-lo localmente.
(Acredito que esse comportamento se originou amplamente de uma otimização de namespaces locais - sem esse comportamento, a VM do Python precisaria executar pelo menos três pesquisas de nome cada vez que um novo nome fosse atribuído dentro de uma função (para garantir que o nome não ' já existe no nível do módulo / interno), o que desaceleraria significativamente uma operação muito comum.)
MyGlobal = 5
x
é local é diferente de verificar no tempo de execução se o nome do local foi associado a um valor antes de ser usado pela primeira vez.
MY_GLOBAL = 5
. Veja o Guia de Estilo para Código Python .
Você pode explorar a noção de namespaces . No Python, o módulo é o local natural para dados globais :
Cada módulo possui sua própria tabela de símbolos privada, que é usada como tabela de símbolos global 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 conflitos acidentais com as variáveis globais de um usuário. Por outro lado, se você souber o que está fazendo, poderá tocar nas variáveis globais de um módulo com a mesma notação usada para se referir a suas funções
modname.itemname
.
Um uso específico de global-in-a-module é descrito aqui - Como faço para compartilhar variáveis globais entre módulos? , e para completar, o conteúdo é compartilhado aqui:
A maneira canônica de compartilhar informações entre módulos em um único programa é criar um módulo de configuração especial (geralmente chamado de config ou cfg ). Basta importar o módulo de configuração em todos os módulos do seu aplicativo; o módulo fica disponível como um nome global. Como há apenas uma instância de cada módulo, quaisquer alterações feitas no objeto do módulo são refletidas em todos os lugares. Por exemplo:
Arquivo: config.py
x = 0 # Default value of the 'x' configuration setting
Arquivo: mod.py
import config config.x = 1
Arquivo: main.py
import config import mod print config.x
config.x
posso me livrar disso? Eu vim com x = lambda: config.x
e então tenho o novo valor em x()
. por alguma razão, ter a = config.x
não faz o truque para mim.
from config import x
resolve isso?
O Python usa uma heurística simples para decidir de qual escopo deve carregar uma variável, entre local e global. Se um nome de variável aparecer no lado esquerdo de uma atribuição, mas não for declarado global, será considerado local. Se ele não aparecer no lado esquerdo de uma atribuição, será considerado 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 tarefa em foo()
, é a única LOAD_FAST
variável.
for
loop e o nome after as
in with
e as except
instruções também estão vinculados.
as
de uma except
cláusula, isso não era óbvio para mim. Mas é excluído automaticamente para economizar memória.
as ...
destino no manipulador de exceções.
Se você quiser se referir a uma variável global em uma função, poderá usar a palavra-chave global para declarar quais variáveis são globais. Você não precisa usá-lo em todos os casos (como alguém aqui afirma incorretamente) - se o nome referenciado em uma expressão não puder ser encontrado no escopo ou nos escopos locais nas funções em que essa função é definida, ela será pesquisada entre os globais variáveis.
No entanto, se você atribuir a uma nova variável não declarada como global na função, ela será declarada implicitamente como local e poderá ofuscar qualquer variável global existente com o mesmo nome.
Além disso, variáveis globais são úteis, ao contrário de alguns fanáticos por OOP que afirmam o contrário - especialmente para scripts menores, onde o OOP é um exagero.
Se eu criar uma variável global em uma função, como posso usar essa variável em outra 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 seu código. Então chamamos a create_global_variable
função:
>>> create_global_variable()
Você pode apenas usá-lo, desde que não espere alterar para qual objeto ele aponta:
Por exemplo,
def use_global_variable():
return global_variable + '!!!'
e agora podemos usar a variável global:
>>> use_global_variable()
'Foo!!!'
Para apontar a variável global para um objeto diferente, você deve usar a palavra-chave global novamente:
def change_global_variable():
global global_variable
global_variable = 'Bar'
Observe que, após escrever esta função, o código que realmente a altera ainda não foi executado:
>>> 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
nome agora aponta para 'Bar'
:
>>> use_global_variable()
'Bar!!!'
Observe que "global" no Python não é verdadeiramente global - é apenas global no nível do módulo. Portanto, ele está disponível apenas para funções escritas nos módulos em que é global. As funções lembram o módulo em que foram gravadas; portanto, quando são exportadas para outros módulos, elas ainda procuram no módulo em que foram criadas para encontrar variáveis globais.
Se você criar uma variável local com o mesmo nome, ela 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 o uso dessa variável local com nome incorreto não altera a variável global:
>>> use_global_variable()
'Bar!!!'
Observe que você deve evitar o uso de variáveis locais com os mesmos nomes de globais, a menos que saiba exatamente o que está fazendo e tenha um bom motivo para fazê-lo. Ainda não encontrei esse motivo.
Um comentário a seguir pergunta:
o que fazer se eu quiser criar uma variável global dentro de uma função dentro de uma classe e desejar usar essa variável dentro de outra função dentro de outra classe?
Aqui, demonstro que temos o mesmo comportamento nos métodos que fazemos nas funções regulares:
class Foo:
def foo(self):
global global_variable
global_variable = 'Foo'
class Bar:
def bar(self):
return global_variable + '!!!'
Foo().foo()
E agora:
>>> Bar().bar()
'Foo!!!'
Mas eu sugiro que, em vez de usar variáveis globais, você use atributos de classe, para evitar sobrecarregar o espaço para nome do módulo. Observe também que não usamos self
argumentos aqui - esses podem ser métodos de classe (úteis se você alterar o atributo de classe do cls
argumento usual ) ou métodos estáticos (não self
ou cls
).
Além das respostas já existentes e para tornar isso mais confuso:
No Python, variáveis referenciadas apenas dentro de uma função são implicitamente globais . Se uma variável receber um novo valor em qualquer parte do corpo da função, será considerado um local . Se alguma vez for atribuído a uma variável um novo valor dentro da função, ela é implicitamente local e você precisará declará-la explicitamente como 'global'.
Embora um pouco surpreendente no começo, um momento de consideração explica isso. Por um lado, exigir global para variáveis atribuídas fornece uma barreira contra efeitos colaterais indesejados. Por outro lado, se global fosse necessário para todas as referências globais, você usaria global o tempo todo. Você teria que declarar como global todas as referências a uma função interna ou a um componente de um módulo importado. Essa confusão derrotaria a utilidade da declaração global para identificar efeitos colaterais.
Fonte: Quais são as regras para variáveis locais e globais no Python? .
Com a execução paralela, variáveis globais podem causar resultados inesperados se você não entender o que está acontecendo. Aqui está um exemplo de uso de uma variável global no multiprocessamento. Podemos ver claramente que cada processo trabalha com sua própria cópia da variável:
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]
Como se vê, a resposta é sempre simples.
Aqui está um pequeno módulo de amostra com uma maneira simples de mostrá-lo em uma main
definição:
def five(enterAnumber,sumation):
global helper
helper = enterAnumber + sumation
def isTheNumber():
return helper
Aqui está como mostrá-lo em uma main
definição:
import TestPy
def main():
atest = TestPy
atest.five(5,8)
print(atest.isTheNumber())
if __name__ == '__main__':
main()
Esse código simples funciona assim e é executado. Espero que ajude.
global_vars
e inicializo os dados init_global_vars
, que estão sendo chamados no script de inicialização. Então, simplesmente crio o método de acessador para cada var global definida. Espero poder votar isso várias vezes! Obrigado Peter!
Você precisa fazer referência à variável global em todas as funções que deseja usar.
Do seguinte modo:
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]
"""
Na verdade, você não está armazenando o global em uma variável local, apenas criando uma referência local para o mesmo objeto ao qual sua referência global original se refere. Lembre-se de que praticamente tudo no Python é um nome referente a um objeto, e nada é copiado na operação usual.
Se você não precisou especificar explicitamente quando um identificador deveria se referir a um global predefinido, presumivelmente teria que especificar explicitamente quando um identificador é uma nova variável local (por exemplo, com algo como o comando 'var' visto em JavaScript). Como as variáveis locais são mais comuns que as globais em qualquer sistema sério e não trivial, o sistema do Python faz mais sentido na maioria dos casos.
Você poderia ter um idioma que tentasse adivinhar, usando uma variável global se ela existisse ou criando uma variável local se não existisse. No entanto, isso seria muito propenso a erros. Por exemplo, a importação de outro módulo pode inadvertidamente introduzir uma variável global com esse nome, alterando o comportamento do seu programa.
Tente o seguinte:
def x1():
global x
x = 6
def x2():
global x
x = x+1
print x
x = 5
x1()
x2() # output --> 7
Caso você tenha uma variável local com o mesmo nome, convém usar a globals()
função .
globals()['your_global_var'] = 42
Após e como complemento, use um arquivo para conter todas as variáveis globais, todas declaradas localmente e, em seguida, import as
:
Arquivo initval.py :
Stocksin = 300
Prices = []
Arquivo getstocks.py :
import initval as iv
def getmystocks():
iv.Stocksin = getstockcount()
def getmycharts():
for ic in range(iv.Stocksin):
import ... as ...
? Por que não apenas import ...
?
global
:-) => +1 :-) Por favor, edite sua resposta para esclarecer esses interrogatórios que outras pessoas também podem ter. Cheers
A gravação em elementos explícitos de uma matriz global aparentemente não precisa da declaração global, embora a gravação em "atacado" 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
Estou adicionando isso porque não o vi em nenhuma das outras respostas e pode ser útil para alguém que está enfrentando algo semelhante. A globals()
função retorna um dicionário de símbolos globais mutável, no qual você pode "magicamente" disponibilizar dados para o restante do seu código. Por exemplo:
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
Apenas permitirá que você faça o dump / carregue variáveis fora e dentro do espaço de nomes global. Super conveniente, sem confusão, sem problemas. Certamente é apenas o Python 3.
globals()
sempre retorna globais disponíveis no contexto local; portanto, uma mutação aqui pode não refletir em outro módulo.
Faça referência ao namespace da classe em que deseja que a alteração seja exibida.
Neste exemplo, o runner está usando max na configuração do arquivo. Quero que meu teste altere o valor de max quando o corredor estiver usando.
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()
Globais em conexão com o multiprocessamento em diferentes plataformas / ambientes, como Windows / Mac OS, por um lado, e Linux, por outro, são problemáticos.
Vou mostrar isso com um exemplo simples, apontando um problema com o qual me deparo há algum tempo atrás.
Se você quer entender, por que as coisas são diferentes no Windows / MacOs e Linux, você precisa saber disso, o mecanismo padrão para iniciar um novo processo no ...
Eles são diferentes na alocação de memória, uma inicialização ... (mas eu não entendo isso aqui).
Vamos dar uma olhada no problema / exemplo ...
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)
Se você executar isso no Windows (e suponho também no MacOS), obterá a seguinte saída ...
task 0: counter = 1
task 1: counter = 2
task 2: counter = 3
task 3: counter = 4
Se você executar isso no Linux, obterá o seguinte.
task 0: counter = 1
task 1: counter = 1
task 2: counter = 1
task 3: counter = 1