La __debug__
variable es útil en parte porque afecta a cada módulo. Si quiero crear otra variable que funcione de la misma manera, ¿cómo lo haría?
La variable (seamos originales y llamémosla 'foo') no tiene que ser verdaderamente global, en el sentido de que si cambio foo en un módulo, se actualiza en otros. Estaría bien si pudiera configurar foo antes de importar otros módulos y luego verían el mismo valor.
hasattr(__builtin__, "foo")
.Si necesita una variable global de módulo cruzado, tal vez solo sea suficiente una variable de nivel de módulo global simple.
a.py:
b.py:
c.py:
Prueba:
Ejemplo del mundo real: global_settings.py de Django (aunque en la configuración de las aplicaciones de Django se utiliza al importar el objeto
django.conf.settings
).fuente
a.py
, contienemain()
? ¿Importa?if __name__=="__main__"
guard para evitar la ejecución de código inesperado en la importación.id()
para verificar identidad)Creo que hay muchas circunstancias en las que tiene sentido y simplifica la programación para tener algunos globales que se conocen en varios módulos (estrechamente acoplados). En este espíritu, me gustaría profundizar un poco en la idea de tener un módulo de globales que sea importado por aquellos módulos que necesitan hacer referencia a ellos.
Cuando solo hay uno de esos módulos, lo llamo "g". En él, asigno valores predeterminados para cada variable que intento tratar como global. En cada módulo que usa alguno de ellos, no uso "from g import var", ya que esto solo da como resultado una variable local que se inicializa desde g solo en el momento de la importación. Hago la mayoría de las referencias en la forma g.var y la "g". sirve como un recordatorio constante de que estoy tratando con una variable que es potencialmente accesible para otros módulos.
Si el valor de dicha variable global se va a usar con frecuencia en alguna función de un módulo, entonces esa función puede hacer una copia local: var = g.var. Sin embargo, es importante darse cuenta de que las asignaciones a var son locales y que g.var global no se puede actualizar sin hacer referencia explícita a g.var en una asignación.
Tenga en cuenta que también puede tener múltiples módulos globales de este tipo compartidos por diferentes subconjuntos de sus módulos para mantener las cosas un poco más controladas. La razón por la que uso nombres cortos para mis módulos globales es para evitar saturar demasiado el código con la aparición de ellos. Con solo un poco de experiencia, se vuelven lo suficientemente mnemotécnicos con solo 1 o 2 caracteres.
Todavía es posible hacer una asignación a, por ejemplo, gx cuando x no estaba definido en g, y un módulo diferente puede acceder a gx. Sin embargo, aunque el intérprete lo permite, este enfoque no es tan transparente, y evito eso. Todavía existe la posibilidad de crear accidentalmente una nueva variable en g como resultado de un error tipográfico en el nombre de la variable para una asignación. A veces, un examen de dir (g) es útil para descubrir cualquier nombre sorpresa que pueda haber surgido por dicho accidente.
fuente
Defina un módulo (llámelo "globalbaz") y tenga las variables definidas dentro de él. Todos los módulos que usan este "pseudoglobal" deberían importar el módulo "globalbaz" y referirse a él usando "globalbaz.var_name"
Esto funciona independientemente del lugar del cambio, puede cambiar la variable antes o después de la importación. El módulo importado utilizará el último valor. (Probé esto en un ejemplo de juguete)
Para aclarar, globalbaz.py se ve así:
fuente
Puede pasar los globales de un módulo a otro:
En el módulo A:
En el módulo B:
fuente
Las variables globales suelen ser una mala idea, pero puede hacerlo asignando a
__builtins__
:Además, los módulos en sí mismos son variables a las que puede acceder desde cualquier módulo. Entonces, si define un módulo llamado
my_globals.py
:Entonces puedes usar eso desde cualquier lugar también:
El uso de módulos en lugar de modificar
__builtins__
es generalmente una forma más limpia de hacer globales de este tipo.fuente
__builtins__
es una peculiaridad de CPython, realmente no deberías usarla - mejor uso__builtin__
(obuiltins
en Python3) como muestra la respuesta aceptadaYa puede hacer esto con variables de nivel de módulo. Los módulos son los mismos sin importar desde qué módulo se estén importando. Por lo tanto, puede hacer que la variable sea una variable de nivel de módulo en cualquier módulo que tenga sentido colocarla y acceder a ella o asignarla desde otros módulos. Sería mejor llamar a una función para establecer el valor de la variable, o para que sea una propiedad de algún objeto singleton. De esa manera, si termina necesitando ejecutar algún código cuando la variable ha cambiado, puede hacerlo sin romper la interfaz externa de su módulo.
Por lo general, no es una buena manera de hacer las cosas, ya que rara vez lo es el uso de los globales, pero creo que esta es la forma más limpia de hacerlo.
fuente
Quería publicar una respuesta de que hay un caso en el que no se encontrará la variable.
Las importaciones cíclicas pueden romper el comportamiento del módulo.
Por ejemplo:
first.py
second.py
main.py
En este ejemplo, debería ser obvio, pero en una base de código grande, esto puede ser realmente confuso.
fuente
Esto suena como modificar el
__builtin__
espacio de nombres. Para hacerlo:No utilice
__builtins__
directamente (observe la "s" adicional), aparentemente puede ser un diccionario o un módulo. Gracias a ΤΖΩΤΖΙΟΥ por señalar esto, se puede encontrar más aquí .Ahora
foo
está disponible para usar en todas partes.No recomiendo hacer esto en general, pero el uso de esto depende del programador.
La asignación debe hacerse como se indicó anteriormente, solo la configuración
foo = 'some-other-value'
solo lo establecerá en el espacio de nombres actual.fuente
Lo uso para un par de funciones primitivas incorporadas que sentí que realmente faltaban. Un ejemplo es una función de búsqueda que tiene la misma semántica de uso que filtro, mapa, reducción.
Una vez que esto se ejecuta (por ejemplo, al importar cerca de su punto de entrada) todos sus módulos pueden usar find () como si, obviamente, estuviera integrado.
Nota: Puede hacer esto, por supuesto, con un filtro y otra línea para probar la longitud cero, o con reducir en un tipo de línea extraña, pero siempre sentí que era extraño.
fuente
Podría lograr variables modificables (o mutables ) entre módulos utilizando un diccionario:
Al iniciar
test_wait_app_up_fail
, la duración real del tiempo de espera es de 3 segundos.fuente
Me preguntaba si sería posible evitar algunas de las desventajas del uso de variables globales (véase, por ejemplo, http://wiki.c2.com/?GlobalVariablesAreBad ) mediante el uso de un espacio de nombres de clase en lugar de un espacio de nombres global / módulo para pasar valores de variables . El siguiente código indica que los dos métodos son esencialmente idénticos. Hay una ligera ventaja en el uso de espacios de nombres de clase como se explica a continuación.
Los siguientes fragmentos de código también muestran que los atributos o variables pueden crearse y eliminarse dinámicamente tanto en espacios de nombres globales / de módulo como en espacios de nombres de clase.
wall.py
Llamo a este módulo 'muro' ya que se usa para rebotar variables. Actuará como un espacio para definir temporalmente variables globales y atributos de toda la clase del 'enrutador' de clase vacía.
source.py
Este módulo importa el muro y define una sola función
sourcefn
que define un mensaje y lo emite mediante dos mecanismos diferentes, uno a través de las funciones globales y otro a través de la función del enrutador. Tenga en cuenta que las variableswall.msg
ywall.router.message
se definen aquí por primera vez en sus respectivos espacios de nombres.dest.py
Este módulo define una función
destfn
que utiliza los dos mecanismos diferentes para recibir los mensajes emitidos por la fuente. Permite la posibilidad de que la variable 'msg' no exista.destfn
también elimina las variables una vez que se han mostrado.main.py
Este módulo llama a las funciones definidas previamente en secuencia. Después de la primera llamada a
dest.destfn
las variableswall.msg
ywall.router.msg
ya no existen.La salida del programa es:
global: Hola mundo!
enrutador: ¡Hola mundo!
global: sin mensaje
enrutador: sin mensaje
Los fragmentos de código anteriores muestran que los mecanismos módulo / global y clase / clase variable son esencialmente idénticos.
Si se van a compartir muchas variables, la contaminación del espacio de nombres se puede gestionar mediante el uso de varios módulos de tipo de pared, por ejemplo, wall1, wall2, etc. o definiendo varias clases de tipo de enrutador en un solo archivo. Este último es un poco más ordenado, por lo que tal vez representa una ventaja marginal para el uso del mecanismo de variable de clase.
fuente