Variable global con importaciones

first.py

myGlobal = "hello" def changeGlobal(): myGlobal="bye" 

segundo.py

 from first import * changeGlobal() print myGlobal 

La salida que obtengo es

Hola

aunque pensé que debería ser

adiós

¿Por qué no cambia la variable global myGlobal después de la llamada a la función changeGlobal() ?

Tratar:

 def changeGlobal(): global myGlobal myGlobal = "bye" 

En realidad, eso tampoco funciona. Cuando import * , crea un nuevo módulo local global myGlobal que es inmune al cambio que pretende (siempre que no esté mutando la variable, vea más abajo). Puedes usar esto en su lugar:

 import nice nice.changeGlobal() print nice.myGlobal 

O:

 myGlobal = "hello" def changeGlobal(): global myGlobal myGlobal="bye" changeGlobal() 

Sin embargo, si su global es un contenedor mutable, ahora tiene una referencia a un mutable y puede ver los cambios realizados en él:

 myGlobal = ["hello"] def changeGlobal(): myGlobal[0] = "bye" 

Una vez tuve la misma preocupación que la tuya y leer la siguiente sección del Rápido y sin dolor de Python Tutorial de Norman Matloff fue realmente una buena ayuda. Esto es lo que necesita entender (copiado del libro de Matloff):

Python no permite realmente las variables globales en el sentido en que C / C ++ lo hace. Un módulo Python importado no tendrá acceso directo a los globales en el módulo que lo importa, ni viceversa.

Por ejemplo, considere estos dos archivos, x.py ,

 # x.py import y def f(): global x x = 6 def main(): global x x = 3 f() yg() if __name__ == '__main__': main() 

y y.py :

 # y.py def g(): global x x += 1 

La variable x en x.py es visible en todo el módulo x.py , pero no en y.py. De hecho, la ejecución de la línea x + = 1.

en el último, aparecerá un mensaje de error, “el nombre global ‘x’ no está definido”.

De hecho, una variable global en un módulo es simplemente un atributo (es decir, una entidad miembro) de ese módulo, similar al rol de una variable de clase dentro de una clase. Cuando el módulo B es importado por el módulo A , el espacio de nombres de B se copia en los de A. Si el módulo B tiene una variable global X, entonces el módulo A creará una variable de ese nombre, cuyo valor inicial es el módulo B que tenía para su variable de ese nombre en el momento de la importación. Pero los cambios a X en uno de los módulos NO se reflejarán en el otro.

Digamos que X cambia en B , pero queremos que el código en A pueda obtener el último valor de X en B. Podemos hacerlo incluyendo una función, por ejemplo llamada GetX () en B. Suponiendo que A importó todo de B , entonces A obtendrá una función GetX () que es una copia de la función de B de ese nombre, y cuyo único propósito es devolver el valor de X. A menos que B cambie esa función (que es posible, por ejemplo, se pueden asignar funciones), las funciones en los dos módulos siempre serán las mismas, y por lo tanto A puede usar su función para obtener el valor de X en B.

Las variables globales de Python no son globales

Como señala wassimans arriba, son esencialmente atributos dentro del scope del módulo en el que están definidos (o el módulo que contiene la función que los definió).

La primera confusión (error) con la que se encuentra la gente es no darse cuenta de que las funciones tienen un espacio de nombres local y que establecer una variable en una función la convierte en una función local de la función, incluso cuando pretendían que cambiara una variable (global) de la misma Nombre en el módulo adjunto. (declarar el nombre en una statement ‘global’ en la función, o acceder a la variable (global) antes de establecerla).

La segunda confusión (error) con la que se encuentra la gente es que cada módulo (es decir, un archivo importado) contiene su propio espacio de nombres denominado ‘global’. Supongo que Python cosas del mundo (globo) es el módulo, tal vez estamos buscando variables ‘universales’ que abarquen más de un globo.

La tercera confusión (que estoy empezando a entender ahora) es ¿dónde están los ‘globales’ en el módulo __main__ ? Es decir, si inicia python desde la línea de comandos en modo interactivo, o si invoca el script de python (escriba el nombre de foo.py desde el comando shell), no hay importación de un módulo cuyo nombre pueda usar.

El contenido de ‘globals ()’ o globals (). Keys () – que le da una lista de los globals – parece ser accesible como: dir (sys.modules [‘ __main__ ‘]) Parece que el módulo para la secuencia de comandos de python cargada (o la sesión interactiva sin secuencia de comandos cargada), la que lleva el nombre: __name__ , no tiene nombre global, pero es accesible como el módulo cuyo nombre es ‘ __main__ ‘ en la lista del sistema de todos los módulos activos, sys .módulos