129 votes

Python : Comment créer une variable inter-module ?

Le site __debug__ est pratique en partie parce qu'elle affecte chaque module. Si je veux créer une autre variable qui fonctionne de la même manière, comment dois-je m'y prendre ?

La variable (soyons originaux et appelons-la 'foo') n'a pas besoin d'être vraiment globale, dans le sens où si je modifie foo dans un module, elle est mise à jour dans les autres. Je serais satisfait si je pouvais définir foo avant d'importer d'autres modules et qu'ils voient alors la même valeur pour cette variable.

178voto

J.F. Sebastian Points 102961

Si vous avez besoin d'une variable globale inter-module, une simple variable globale au niveau du module peut suffire.

a.py :

var = 1

b.py :

import a
print a.var
import c
print a.var

c.py :

import a
a.var = 2

Test :

$ python b.py
# -> 1 2

Exemple concret : Le fichier global_settings.py de Django (bien que dans les applications Django, les paramètres sont utilisés en important le fichier objet django.conf.settings ).

3 votes

Meilleur car il évite les éventuels conflits d'espace de noms

0 votes

Et si le module que vous importez, dans ce cas-ci a.py , contient main() ? Est-ce important ?

4 votes

@sedeh : non. Si a.py est également exécuté en tant que script alors utilisez if __name__=="__main__" pour éviter l'exécution d'un code inattendu lors de l'importation.

120voto

Curt Hagenlocher Points 12432

Je n'approuve pas cette solution de quelque manière que ce soit. Mais si vous ajoutez une variable à la __builtin__ il sera accessible comme s'il s'agissait d'un global de n'importe quel autre module qui inclut le module __builtin__ -- c'est-à-dire tous, par défaut.

a.py contient

print foo

b.py contient

import __builtin__
__builtin__.foo = 1
import a

Le résultat est que "1" est imprimé.

Edit : Le site __builtin__ est disponible en tant que symbole local __builtins__ -- c'est la raison de la divergence entre deux de ces réponses. Notez également que __builtin__ a été renommé en builtins dans python3.

2 votes

Y a-t-il une raison pour laquelle vous n'aimez pas cette situation ?

40 votes

D'une part, cela brise les attentes des gens lorsqu'ils lisent du code. "C'est quoi ce symbole 'foo' utilisé ici ? Pourquoi je ne peux pas voir où il est défini ?"

10 votes

Il est également susceptible de faire des ravages si une version future de Python commence à utiliser le nom que vous avez choisi comme un buildin réel.

30voto

Je pense qu'il y a de nombreuses circonstances dans lesquelles cela a du sens et simplifie la programmation d'avoir quelques globaux qui sont connus à travers plusieurs modules (étroitement couplés). Dans cet esprit, je voudrais développer un peu l'idée d'avoir un module de globaux qui est importé par les modules qui ont besoin de les référencer.

Lorsqu'il n'y a qu'un seul module de ce type, je le nomme "g". Dans ce module, j'attribue des valeurs par défaut à toutes les variables que j'ai l'intention de traiter comme globales. Dans chaque module qui utilise l'une d'entre elles, je n'utilise pas "from g import var", car cela ne donne qu'une variable locale qui n'est initialisée à partir de g qu'au moment de l'importation. Je fais la plupart des références sous la forme g.var, et le "g." sert de rappel constant que je traite une variable qui est potentiellement accessible à d'autres modules.

Si la valeur d'une telle variable globale doit être utilisée fréquemment dans une fonction d'un module, alors cette fonction peut en faire une copie locale : var = g.var. Cependant, il est important de réaliser que les affectations à var sont locales, et que la variable globale g.var ne peut pas être mise à jour sans faire référence à g.var explicitement dans une affectation.

Notez que vous pouvez également avoir plusieurs modules globaux de ce type partagés par différents sous-ensembles de vos modules pour garder les choses un peu plus étroitement contrôlées. La raison pour laquelle j'utilise des noms courts pour mes modules globaux est d'éviter de trop encombrer le code avec leurs occurrences. Avec un peu d'expérience, ils deviennent suffisamment mnémotechniques avec seulement 1 ou 2 caractères.

Il est toujours possible de faire une affectation à, disons, g.x lorsque x n'était pas déjà défini dans g, et un autre module peut alors accéder à g.x. Cependant, même si l'interpréteur le permet, cette approche n'est pas si transparente, et je l'évite. Il y a toujours la possibilité de créer accidentellement une nouvelle variable dans g à la suite d'une faute de frappe dans le nom de la variable pour une affectation. Parfois, un examen de dir(g) est utile pour découvrir tous les noms surprenants qui ont pu apparaître par un tel accident.

9 votes

Cette observation intéressante a résolu mon problème : 'Je n'utilise pas "from g import var", car cela ne donne qu'une variable locale qui n'est initialisée depuis g qu'au moment de l'importation.' Il semble raisonnable de supposer que "from..import" est identique à "import" mais ce n'est pas vrai.

27voto

hayalci Points 2161

Définissez un module (appelez-le "globalbaz") et définissez-y les variables. Tous les modules utilisant ce "pseudoglobal" doivent importer le module "globalbaz" et s'y référer en utilisant "globalbaz.var_name".

Cela fonctionne quel que soit le lieu de la modification, vous pouvez modifier la variable avant ou après l'importation. Le module importé utilisera la dernière valeur. (J'ai testé ceci dans un exemple de jouet)

Pour clarifier, globalbaz.py ressemble à ceci :

var_name = "my_useful_string"

11voto

user394430 Points 161

Vous pouvez passer les globaux d'un module à un autre :

Dans le module A :

import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var

Dans le module B :

def do_something_with_my_globals(glob): # glob is simply a dict.
    glob["my_var"]=3

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X