2010-12-14 7 views
10

Me sorprendió descubrir queConfirmación de la diferencia entre las importaciones y desde * * xxx importación

import foo 

y

from foo import * 

tenían diferentes efectos sobre los miembros globales. Quería confirmar que mis experimentos son el comportamiento correcto.

En el primer ejemplo, cambiar un miembro en el módulo foo se reflejará en todo el código que importa foo. Sin embargo, cambiar ese miembro en el último caso solo parece afectar el archivo en el que se importó. En otras palabras, usar el enfoque posterior le dará a cada archivo de importación su propia copia de los miembros de foo.

el comportamiento que quiero es tener acceso a foo.x desde todos los archivos, poder cambiarlo de todos los archivos, y tener ese cambio reflejado en todos los archivos (un verdadero global si se quiere).

Respuesta

14

Sí, sus observaciones son correctas. Esto es una consecuencia de la forma en que el enlace funciona en Python.

Cuando uno hace

import foo 

continuación foo se convierte en un nombre global que hace referencia al módulo de foo. Cuando uno hace

foo.bar = 7 

Luego se sigue el de referencia y el objeto foo se carga. Entonces 7 se almacena en el atributo bar.

Cuando otro módulo importa foo, simplemente saca el objeto de sys.modules['foo'] y obtiene el valor modificado.

Cuando uno hace

from foo import bar 

globals()['bar'] se establece en referencia a foo.bar. Cuando uno hace tarde

bar = 7 

globals()['bar'] ya no hace referencia a foo.bar, pero las referencias de una copia de 7. Es decir, el enlace original en el alcance global del módulo de importación simplemente se reemplaza.

En el primer ejemplo, uno está modificando los atributos de un objeto que está almacenado en sys.modules y será común a todos los módulos que lo hayan importado. En el segundo ejemplo, uno está modificando el alcance global del módulo de importación.

Si uno iba a hacer algo en la línea de

from foo import fobaz 
fobaz.foobar = 7 

Luego de que el cambio sería se propagará a otros módulos que importan porque uno no es sobrescribir la referencia global, pero siguiente para modificar un atributo del objeto al que apunta. Entonces, esencialmente, debería poder modificar objetos mutables siempre que no sobrescriba el enlace global.

Creo que algo así es lo más cercano que podrás llegar limpiamente a un verdadero mundo en python. Como lenguaje, valora mucho los espacios de nombres.

+0

Guau, yo no sabía esto. Buena respuesta. – invert

4

Considerando que las variables globales generalmente se consideran malas, sospecho que una variable "verdadera global" sería algo extremadamente malo.

Otra forma de obtener un comportamiento similar es utilizar los atributos de clase-alcance en un objeto singleton, e importar eso. Entonces está más claro de dónde está obteniendo la variable "global".

+0

Ese es un buen punto, gracias por su respuesta. –

Cuestiones relacionadas