Esto es lo que está pasando.
Primero, las únicas variables globales que realmente tiene Python son las variables con ámbito de módulo. No puedes hacer una variable que sea verdaderamente global; Todo lo que puedes hacer es crear una variable en un ámbito particular. (Si crea una variable dentro del intérprete de Python y luego importa otros módulos, su variable está en el alcance más externo y, por tanto, global dentro de su sesión de Python).
Todo lo que tiene que hacer para crear una variable module-global es solo asigne un nombre.
imaginar un archivo llamado foo.py, que contiene esta sola línea:
X = 1
Ahora imaginemos lo importa.
import foo
print(foo.X) # prints 1
Sin embargo, supongamos que desea utilizar una de las variables de módulo de alcance mundial como dentro de una función, como en el ejemplo. El valor predeterminado de Python es suponer que las variables de función son locales. Simplemente agrega una declaración global
en su función, antes de intentar usar el global.
def initDB(name):
global __DBNAME__ # add this line!
if __DBNAME__ is None: # see notes below; explicit test for None
__DBNAME__ = name
else:
raise RuntimeError("Database name has already been set.")
Por cierto, para este ejemplo, el simple análisis de if not __DBNAME__
es adecuada, ya que cualquier valor de cadena que no sea una cadena vacía evaluará cierto, por lo que cualquier nombre de base de datos real evaluará cierto. Pero para las variables que pueden contener un valor numérico que podría ser 0, no puede simplemente decir if not variablename
; en ese caso, debe probar explícitamente None
usando el operador is
. Modifiqué el ejemplo para agregar una prueba explícita None
. La prueba explícita para None
nunca es incorrecta, así que de manera predeterminada la uso.
Finalmente, como han señalado otros en esta página, dos guiones subrayan a Python que desea que la variable sea "privada" para el módulo. Si alguna vez hace un import * from mymodule
, Python no importará nombres con dos guiones bajos principales en su espacio de nombres. Pero si solo hace un simple import mymodule
y luego dice dir(mymodule)
verá las variables "privadas" en la lista, y si se refiere explícitamente a mymodule.__DBNAME__
Python no le importará, solo le permitirá consultarlo. Los guiones bajos dobles son una pista importante para los usuarios de su módulo de que no desea que vuelvan a enlazar ese nombre con algún valor propio.
Se considera la mejor práctica en Python no hacer import *
, pero para minimizar el acoplamiento y maximizar explícito, ya sea usando mymodule.something
o por hacer explícita una importación como from mymodule import something
.
EDITAR: Si, por alguna razón, necesita hacer algo como esto en una versión muy antigua de Python que no tiene la palabra clave global
, hay una solución fácil. En lugar de establecer directamente una variable global de módulo, use un tipo mutable en el nivel global del módulo y almacene sus valores dentro de él.
En sus funciones, el nombre de la variable global será de solo lectura; no podrá volver a enlazar el nombre de la variable global real. (Si asigna un nombre de variable dentro de su función, solo afectará el nombre de la variable local dentro de la función). Pero puede usar ese nombre de variable local para acceder al objeto global real y almacenar datos dentro de él.
Se puede utilizar un list
pero su código será feo:
__DBNAME__ = [None] # use length-1 list as a mutable
# later, in code:
if __DBNAME__[0] is None:
__DBNAME__[0] = name
Un dict
es mejor. Sin embargo, lo más conveniente es una instancia de clase, y sólo se puede utilizar una clase trivial: (. Usted realmente no necesita para capitalizar la variable nombre de la base de datos)
class Box:
pass
__m = Box() # m will contain all module-level values
__m.dbname = None # database name global in module
# later, in code:
if __m.dbname is None:
__m.dbname = name
me gusta el azúcar sintáctica de solo usando __m.dbname
en lugar de __m["DBNAME"]
; parece la solución más conveniente en mi opinión. Pero la solución dict
también funciona bien.
Con un dict
puede usar cualquier valor hashable como clave, pero cuando esté satisfecho con los nombres que son identificadores válidos, puede usar una clase trivial como Box
en el cuadro anterior.
Gracias a todos por las excelentes respuestas! Aprendí mucho más sobre Python de lo que esperaba. – daveslab