Voici ce qui se passe.
Tout d'abord, les seules variables globales Python vraiment a sont de module d'étendue variables. Vous ne pouvez pas faire une variable qui est vraiment mondial; tout ce que vous pouvez faire est de faire une variable dans un champ particulier. (Si vous faites une variable à l'intérieur de l'interpréteur Python, et puis les importer d'autres modules, la variable est à l'extérieur de la portée et donc mondiale au sein de votre Python session.)
Tout ce que vous avez à faire pour faire un module variable globale est juste d'attribuer à un nom.
Imaginez un fichier appelé foo.py contenant cette seule ligne:
X = 1
Maintenant, imaginez que vous importez.
import foo
print(foo.X) # prints 1
Cependant, supposons que vous souhaitez utiliser l'un de vos module-portée des variables global à l'intérieur d'une fonction, comme dans votre exemple. Python par défaut est de supposer que la fonction de variables sont locales. Il suffit d'ajouter un global
déclaration dans votre fonction, avant d'essayer d'utiliser le mondial.
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.")
Par ailleurs, pour cet exemple, le simple if not __DBNAME__
test est suffisant, parce que toute la chaîne de valeur autre qu'une chaîne vide évaluer la valeur true, donc aucun nom de base de données permettra d'évaluer vrai. Mais pour les variables qui peuvent contenir une valeur numérique qui peut être 0, vous ne pouvez pas dire if not variablename
; dans ce cas, vous devez explicitement test pour None
à l'aide de l' is
de l'opérateur. J'ai modifié l'exemple d'ajouter une explicite None
de test. Le test explicite pour None
ne se trompe jamais, j'ai donc par défaut à utiliser.
Enfin, comme d'autres l'ont noté sur cette page, les deux principaux traits de soulignement signaux de Python que vous voulez de la variable "privé" pour le module. Si jamais vous ne l' import * from mymodule
, Python ne pas importer des noms avec les deux principaux traits de soulignement dans votre espace de nom. Mais si vous venez de faire un simple import mymodule
puis dire, dir(mymodule)
, vous verrez le "privé", les variables dans la liste, et si vous explicitement référence à l' mymodule.__DBNAME__
Python ne sera pas un souci, il sera tout simplement vous permettre de les consulter. Le double principaux traits de soulignement sont un indice majeur pour les utilisateurs de votre module que vous ne voulez pas qu'ils effectuent ce nom à une certaine valeur de leur propre.
Il est considéré comme la meilleure pratique en Python de ne pas faire d' import *
, mais pour minimiser le couplage et de maximiser la précision en utilisant mymodule.something
ou explicitement d'effectuer une importation comme from mymodule import something
.
EDIT: Si, pour une raison quelconque, vous avez besoin de faire quelque chose comme cela dans une très vieille version de Python qui n'ont pas l' global
mot-clé, il est facile de solution de contournement. Au lieu de mettre un module variable globale directement, utilisez une mutable type du module niveau mondial, et de stocker vos valeurs à l'intérieur.
Dans vos fonctions, le nom de la variable globale sera en lecture seule, vous ne serez pas en mesure de relier le réel nom de la variable globale. (Si vous attribuez à ce nom de variable à l'intérieur de votre fonction, il affectera seulement le nom de variable locale à l'intérieur de la fonction.) Mais vous pouvez utiliser ce nom de variable locale pour accéder à l'effectif global de l'objet, et de stocker des données à l'intérieur.
Vous pouvez utiliser un list
mais votre code sera moche:
__DBNAME__ = [None] # use length-1 list as a mutable
# later, in code:
if __DBNAME__[0] is None:
__DBNAME__[0] = name
Un dict
, c'est mieux. Mais le plus pratique est une instance de classe, et vous pouvez simplement utiliser un trivial classe:
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
(Vous n'avez pas vraiment besoin pour tirer profit de la base de données nom de la variable).
J'aime le sucre syntaxique de simplement en utilisant __m.dbname
plutôt que d' __m["DBNAME"]
; il semble que la solution la plus pratique à mon avis. Mais l' dict
solution fonctionne très bien aussi.
Avec un dict
vous pouvez utiliser n'importe quel hashable valeur comme une clé, mais quand vous êtes heureux avec des noms qui sont des identificateurs valides, vous pouvez utiliser un trivial classe comme Box
dans le ci-dessus.