¿Razón para globals () en Python?

¿Cuál es la razón de tener la función globals () en Python? Solo devuelve el diccionario de variables globales, que ya son globales, por lo que se pueden usar en cualquier lugar … Lo pido solo por curiosidad, tratando de aprender python.

def F(): global x x = 1 def G(): print(globals()["x"]) #will return value of global 'x', which is 1 def H(): print(x) #will also return value of global 'x', which, also, is 1 F() G() H() 

¿Realmente no puedo ver el punto aquí? El único momento en que lo necesitaría sería si tuviera variables locales y globales, con el mismo nombre para ambos.

 def F(): global x x = 1 def G(): x = 5 print(x) #5 print(globals()["x"]) #1 F() G() 

Pero nunca debe tener el problema de tener dos variables con el mismo nombre y la necesidad de usarlas dentro del mismo ámbito.

Related of "¿Razón para globals () en Python?"

Python le da al progtwigdor una gran cantidad de herramientas para inspeccionar el entorno en ejecución. globals() es solo uno de esos, y puede ser muy útil en una sesión de depuración para ver qué objetos contiene realmente el scope global.

La razón detrás de esto, estoy seguro, es la misma que la de usar locals() para ver las variables definidas en una función, o usar dir para ver el contenido de un módulo, o los atributos de un objeto.

Con antecedentes en C ++, puedo entender que estas cosas parecen innecesarias. En un entorno estáticamente vinculado, estáticamente tipificado, absolutamente lo serían. En ese caso, en el momento de la comstackción se sabe exactamente qué variables son globales y qué miembros tendrá un objeto, e incluso qué nombres son exportados por otra unidad de comstackción.

En un lenguaje dynamic, sin embargo, estas cosas no son fijas; pueden cambiar dependiendo de cómo se importe el código, o incluso durante el tiempo de ejecución. Por esa razón, al menos, tener acceso a este tipo de información en un depurador puede ser invaluable.

También es útil cuando necesita llamar a una función usando el nombre de cadena de la función. Por ejemplo:

 def foo(): pass function_name_as_string = 'foo' globals()[function_name_as_string]() # foo(). 

Puede pasar el resultado de globals() y locals() a los comandos eval , execfile y __import__ . Al hacerlo, se crea un entorno restringido para que funcionen esos comandos.

Por lo tanto, estas funciones existen para admitir otras funciones que se benefician de recibir un entorno potencialmente diferente del contexto actual. Por ejemplo, podría llamar a globals() luego eliminar o agregar algunas variables antes de llamar a una de esas funciones.

globals() es útil para eval() : si desea evaluar algún código que se refiera a las variables en el scope, esas variables estarán en globals o locals.


Para expandir un bit, la función incorporada eval() interpretará una cadena de código Python que se le asigna. La firma es: eval(codeString, globals, locals) , y la eval(codeString, globals, locals) así:

 def foo(): x = 2 y = eval("x + 1", globals(), locals()) print("y=" + y) # should be 3 

Esto funciona, porque el intérprete obtiene el valor de x del dictado de variables locals() . Por supuesto, puede proporcionar su propio dictado de variables para evaluar.

Puede ser útil en ‘python declarativo’. Por ejemplo, en el siguiente FooDef y BarDef son clases usadas para definir una serie de estructuras de datos que luego son utilizadas por algún paquete como su entrada, o su configuración. Esto le permite mucha flexibilidad en lo que es su entrada, y no necesita escribir un analizador.

 # FooDef, BarDef are classes Foo_one = FooDef("This one", opt1 = False, valence = 3 ) Foo_two = FooDef("The other one", valence = 6, parent = Foo_one ) namelist = [] for i in range(6): namelist.append("nm%03d"%i) Foo_other = FooDef("a third one", string_list = namelist ) Bar_thing = BarDef( (Foo_one, Foo_two), method = 'depth-first') 

Tenga en cuenta que este archivo de configuración utiliza un bucle para crear una lista de nombres que forman parte de la configuración de Foo_other . Por lo tanto, este lenguaje de configuración viene con un “preprocesador” muy poderoso, con una biblioteca de tiempo de ejecución disponible. En caso de que desee, digamos, buscar un registro complejo, o extraer elementos de un archivo zip y decodificarlos por parte de base64, como parte de la generación de su configuración (este enfoque no se recomienda, por supuesto, para los casos en que la entrada puede ser de un archivo comprimido). fuente no confiable …)

El paquete lee la configuración usando algo como lo siguiente:

 conf_globals = {} # make a namespace # Give the config file the classes it needs conf_globals['FooDef']= mypkgconfig.FooDef # both of these are based ... conf_globals['BarDef']= mypkgconfig.BarDef # ... on .DefBase fname = "user.conf" try: exec open(fname) in conf_globals except Exception: ...as needed... # now find all the definitions in there # (I'm assuming the names they are defined with are # significant to interpreting the data; so they # are stored under those keys here). defs = {} for nm,val in conf_globals.items(): if isinstance(val,mypkgconfig.DefBase): defs[nm] = val 

Por lo tanto, para llegar al punto, globals() es útil, cuando se usa un paquete de este tipo, si desea remendar una serie de definiciones de manera procesal:

 for idx in range(20): varname = "Foo_%02d" % i globals()[varname]= FooDef("one of several", id_code = i+1, scale_ratio = 2**i) 

Esto es equivalente a escribir

 Foo_00 = FooDef("one of several", id_code = 1, scale_ratio=1) Foo_01 = FooDef("one of several", id_code = 2, scale_ratio=2) Foo_02 = FooDef("one of several", id_code = 3, scale_ratio=4) ... 17 more ... 

Un ejemplo de un paquete que obtiene su entrada al recostackr un conjunto de definiciones de un módulo de Python es PLY (Python-lex-yacc) http://www.dabeaz.com/ply/ – en ese caso, los objetos son en su mayoría funciones Los objetos, pero los metadatos de los objetos de función (sus nombres, cadenas de documentación y orden de definición) también forman parte de la entrada. No es un buen ejemplo para el uso de globals() . Además, se importa mediante la “configuración”, esta última es una secuencia de comandos de Python normal, y no al revés.

He usado ‘python declarativo’ en algunos proyectos en los que he trabajado, y he tenido la oportunidad de usar globals() al escribir configuraciones para esos. Ciertamente, se podría argumentar que esto se debió a una debilidad en la forma en que se diseñó el ‘idioma’ de la configuración. El uso de globals() de esta manera no produce resultados muy claros; solo resultados que pueden ser más fáciles de mantener que escribir una docena de declaraciones casi idénticas.

También puede usarlo para dar importancia a las variables dentro del archivo de configuración, de acuerdo con sus nombres:

 # All variables above here starting with Foo_k_ are collected # in Bar_klist # foo_k = [ v for k,v in globals().items() if k.startswith('Foo_k_')] Bar_klist = BarDef( foo_k , method = "kset") 

Este método podría ser útil para cualquier módulo de Python que defina muchas tablas y estructuras, para que sea más fácil agregar elementos a los datos, sin tener que mantener las referencias también.

También se puede usar para obtener una instancia de la clase ‘classname’ de una cadena:

 class C: def __init__(self, x): self.x = x print('Added new instance, x:', self.x) def call(str): obj = globals()[str](4) return obj c = call('C') print(cx)