Usando variables globales en una función
-
05-07-2019 - |
Pregunta
¿Cómo puedo crear o usar una variable global en una función?
Si creo una variable global en una función, ¿cómo puedo usar esa variable global en otra función? ¿Necesito almacenar la variable global en una variable local de la función que necesita su acceso?
Solución
Puede usar una variable global en otras funciones declarándola como global
en cada función que le asigne:
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 la razón es que, dado que las variables globales son muy peligrosas, Python quiere asegurarse de que realmente sabes con qué estás jugando, al requerir explícitamente la palabra clave global
. / p>
Vea otras respuestas si desea compartir una variable global entre los módulos.
Otros consejos
Si entiendo tu situación correctamente, lo que estás viendo es el resultado de cómo Python maneja los espacios de nombres locales (función) y globales (módulo).
Digamos que tienes un módulo como este:
# sample.py
myGlobal = 5
def func1():
myGlobal = 42
def func2():
print myGlobal
func1()
func2()
Puede esperar que esto se imprima 42, pero en su lugar imprime 5. Como ya se mencionó, si agrega una declaración ' global
' a func1 ()
, entonces func2 ()
se imprimirá 42.
def func1():
global myGlobal
myGlobal = 42
Lo que sucede aquí es que Python asume que cualquier nombre que esté asignado a , en cualquier lugar dentro de una función, es local a esa función a menos que se indique explícitamente lo contrario. Si solo está leyendo de un nombre, y el nombre no existe localmente, intentará buscar el nombre en cualquier ámbito que contenga (por ejemplo, el alcance global del módulo).
Cuando asignas 42 al nombre myGlobal
, Python crea una variable local que oculta la variable global del mismo nombre. Ese local queda fuera del alcance y es recogida de basura cuando func1 ()
devuelve; Mientras tanto, func2 ()
nunca puede ver otra cosa que no sea el nombre global (sin modificar). Tenga en cuenta que esta decisión sobre el espacio de nombres se produce en tiempo de compilación, no en tiempo de ejecución; si leyó el valor de myGlobal
dentro de func1 ()
antes de asignarlo, Obtenga un UnboundLocalError
, porque Python ya ha decidido que debe ser una variable local pero aún no tiene ningún valor asociado. Pero al usar la declaración ' global
', le dice a Python que debe buscar el nombre en otro lugar en lugar de asignarlo localmente.
(Creo que este comportamiento se originó en gran medida a través de una optimización de espacios de nombres locales; sin este comportamiento, la máquina virtual de Python tendría que realizar al menos tres búsquedas de nombres cada vez que se asigne un nuevo nombre dentro de una función (para garantizar que el nombre no existía ya a nivel de módulo / integrado), lo que ralentizaría significativamente una operación muy común.
Es posible que desee explorar la noción de namespaces . En Python, el módulo es el lugar natural para global datos:
Cada módulo tiene su propia tabla de símbolos privada, que se utiliza como tabla de símbolos global por todas las funciones definidas en el módulo. Por lo tanto, el autor de un módulo puede usar variables globales en el módulo sin preocuparse por choques accidentales con las variables globales de un usuario. Por otra parte, si sabe lo que está haciendo, puede tocar las variables globales de un módulo con la misma notación utilizada para referirse a sus funciones,
modname.itemname
.
Un uso específico de global-in-a-module se describe aquí - ¿Cómo comparto las variables globales entre los módulos? , y para completar el contenido, se comparten aquí:
La forma canónica de compartir información a través de módulos dentro de un solo programa es crear un módulo de configuración especial (a menudo llamado config o cfg ). Solo importa el módulo de configuración en todos los módulos de tu aplicación; el módulo entonces estará disponible como un nombre global. Debido a que solo hay una instancia de cada módulo, los cambios realizados en el objeto del módulo se reflejan en todas partes. Por ejemplo:
Archivo: config.py
x = 0 # Default value of the 'x' configuration setting
Archivo: mod.py
import config config.x = 1
Archivo: main.py
import config import mod print config.x
Python utiliza una heurística simple para decidir desde qué ámbito debe cargar una variable, entre local y global. Si aparece un nombre de variable en el lado izquierdo de una asignación, pero no se declara global, se asume que es local. Si no aparece en el lado izquierdo de una asignación, se asume que es 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
>>>
Vea cómo baz, que aparece en el lado izquierdo de una asignación en foo ()
, es la única variable LOAD_FAST
.
Si desea referirse a una variable global en una función, puede usar la palabra clave global para declarar qué variables son globales. No tiene que usarlo en todos los casos (como dice alguien aquí incorrectamente): si el nombre al que se hace referencia en una expresión no se puede encontrar en el ámbito local o en los ámbitos en las funciones en las que se define esta función, se busca entre variables.
Sin embargo, si asigna una nueva variable no declarada como global en la función, se declara implícitamente como local y puede eclipsar cualquier variable global existente con el mismo nombre.
Además, las variables globales son útiles, al contrario de algunos fanáticos de la OOP que afirman lo contrario, especialmente para scripts más pequeños, donde la OOP es una exageración.
Además de las respuestas ya existentes y para hacerlo más confuso:
En Python, las variables a las que solo se hace referencia dentro de una función son implícitamente global . Si a una variable se le asigna un nuevo valor en cualquier lugar dentro del cuerpo de la función, se supone que es un local . Si una variable siempre se le asigna un nuevo valor dentro de la función, la variable es implícitamente local, y usted debe declararlo explícitamente como "global".
Aunque un poco sorprendente al principio, la consideración de un momento explica esta. Por un lado, la exigencia global de variables asignadas proporciona una Barra contra los efectos secundarios no deseados. Por otro lado, si global fuera requerido para todas las referencias globales, estaría usando global todo el hora. Tendría que declarar como global cada referencia a un Función o a un componente de un módulo importado. Este desorden sería derrotar la utilidad de la declaración global para identificar efectos secundarios.
Fuente: ¿Cuáles son las reglas para las variables locales y globales en Python? .
Si creo una variable global en una función, ¿cómo puedo usar esa variable en otra función?
Podemos crear un global con la siguiente función:
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'
Escribir una función en realidad no ejecuta su código. Así que llamamos a la función create_global_variable
:
>>> create_global_variable()
Usando globales sin modificación
Puedes usarlo, siempre y cuando no esperes cambiar a qué objeto apunta:
Por ejemplo,
def use_global_variable():
return global_variable + '!!!'
y ahora podemos usar la variable global:
>>> use_global_variable()
'Foo!!!'
Modificación de la variable global desde dentro de una función
Para apuntar la variable global a un objeto diferente, debe usar la palabra clave global nuevamente:
def change_global_variable():
global global_variable
global_variable = 'Bar'
Tenga en cuenta que después de escribir esta función, el código que la está cambiando todavía no se ha ejecutado:
>>> change_global_variable()
Después de llamar a la función:
>>> use_global_variable()
'Bar!!!'
podemos ver que la variable global ha sido cambiada. El nombre global_variable
ahora apunta a 'Bar'
:
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!!!'
Tenga en cuenta que " global " en Python no es realmente global, solo es global al nivel de módulo. Por lo tanto, solo está disponible para funciones escritas en los módulos en los que es global. Las funciones recuerdan el módulo en el que están escritas, de modo que cuando se exportan a otros módulos, siguen buscando en el módulo en el que se crearon para encontrar variables globales.
Variables locales con el mismo nombre
Si creas una variable local con el mismo nombre, eclipsará una variable global:
<*>Pero usar esa variable local mal nombrada no cambia la variable global:
<*>Tenga en cuenta que debe evitar el uso de las variables locales con los mismos nombres que los globales, a menos que sepa exactamente lo que está haciendo y tenga una muy buena razón para hacerlo. Todavía no he encontrado tal razón.
Con la ejecución paralela, las variables globales pueden causar resultados inesperados si no entiendes lo que está sucediendo. Este es un ejemplo del uso de una variable global dentro de multiprocesamiento. Podemos ver claramente que cada proceso funciona con su propia copia de la 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]
Resulta que la respuesta es siempre simple.
Aquí hay un pequeño módulo de muestra con una forma sencilla de mostrarlo en una definición de main
:
def five(enterAnumber,sumation):
global helper
helper = enterAnumber + sumation
def isTheNumber():
return helper
Aquí se muestra cómo mostrarlo en una definición de main
:
import TestPy
def main():
atest = TestPy
atest.five(5,8)
print(atest.isTheNumber())
if __name__ == '__main__':
main()
Este simple código funciona así, y se ejecutará. Espero que ayude.
Lo que estás diciendo es usar el método así:
globvar = 5
def f():
var = globvar
print(var)
f() # Prints 5
Pero la mejor manera es usar la variable global de esta manera:
globavar = 5
def f():
global globvar
print(globvar)
f() #prints 5
Ambos dan el mismo resultado.
Debe hacer referencia a la variable global en cada función que desee usar.
De la siguiente manera:
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]
"""
En realidad, no está almacenando el global en una variable local, simplemente creando una referencia local al mismo objeto al que se refiere su referencia global original. Recuerde que prácticamente todo en Python es un nombre que se refiere a un objeto, y nada se copia en la operación habitual.
Si no tuvo que especificar explícitamente cuándo un identificador debía referirse a un global predefinido, entonces probablemente tendría que especificar explícitamente cuándo un identificador es una nueva variable local (por ejemplo, con algo como ' comando var 'visto en JavaScript). Dado que las variables locales son más comunes que las variables globales en cualquier sistema serio y no trivial, el sistema de Python tiene más sentido en la mayoría de los casos.
Usted podría tener un idioma que intentó adivinar, usar una variable global si existía o crear una variable local si no existiera. Sin embargo, eso sería muy propenso a errores. Por ejemplo, importar otro módulo podría introducir inadvertidamente una variable global con ese nombre, cambiando el comportamiento de su programa.
Prueba esto:
def x1():
global x
x = 6
def x2():
global x
x = x+1
print x
x = 5
x1()
x2() # output --> 7
En caso de que tenga una variable local con el mismo nombre, puede usar la globals ()
función .
globals()['your_global_var'] = 42
Siguiendo y como complemento, use un archivo para contener todas las variables globales declaradas localmente y luego importar como
:
Archivo initval.py :
Stocksin = 300
Prices = []
Archivo getstocks.py :
import initval as iv
def getmystocks():
iv.Stocksin = getstockcount()
def getmycharts():
for ic in range(iv.Stocksin):
La escritura en elementos explícitos de una matriz global no parece necesitar la declaración global, aunque se escribe en ella " wholesale " tiene ese 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
Haga referencia al espacio de nombres de la clase donde desea que se muestre el cambio.
En este ejemplo, el corredor está usando max de la configuración del archivo. Quiero que mi prueba cambie el valor de max cuando el corredor la está utilizando.
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()
Estoy agregando esto porque no lo he visto en ninguna de las otras respuestas y podría ser útil para alguien que está luchando con algo similar. La función globals ()
devuelve un mutable global diccionario de símbolos donde puedes " mágicamente " Haga que los datos estén disponibles para el resto de su código.
Por ejemplo:
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
y
from pickle import dump
def dumpfile(name):
with open(name+".dat", "wb") as outfile:
dump(globals()[name], outfile)
return True
Simplemente le permitirá volcar / cargar variables desde y hacia el espacio de nombres global. Súper conveniente, no muss, sin problemas. Bastante seguro de que es solo Python 3.