La variable __all__ est une liste de chaînes de caractères définie dans un module Python.
Elle spécifie quels symboles (fonctions, classes, variables, etc.) d'un module doivent être exportés lorsque l'on utilise l'instruction d'importation générique from module import * .
En l'absence de cette variable, Python exportera tous les symboles qui ne commencent pas par un underscore (_) lors de l'importation avec le wildcard (*).
Utilité
La variable __all__ permet de contrôler précisément quels éléments d'un module seront disponibles à l'importation lorsque l'on utilise *from module import * *.
Cela aide à encapsuler et à organiser le code en exposant seulement les parties nécessaires d'un module, évitant ainsi l'importation de symboles non désirés et la pollution de l'espace de noms.
Cas d'utilisation
1. Encapsulation et abstraction :
En limitant l'exportation aux éléments nécessaires, vous pouvez cacher les détails d'implémentation et exposer uniquement les interfaces publiques.
2. Prévention de la pollution de l'espace de noms :
En définissant explicitement les symboles à exporter, vous évitez d'importer accidentellement des symboles internes ou privés qui peuvent interférer avec d'autres parties de votre code.
3. Amélioration de la lisibilité et de la maintenabilité :
En tant que développeur, cela nous permet ainsi de rapidement identifier les éléments d'un module qui sont destinés à être utilisés publiquement en regardant la variable __all__.
Exemple d'utilisation
Supposons que vous avez un module mon_module.py avec plusieurs fonctions et classes, certaines étant destinées à un usage interne uniquement.
# mon_module.py __all__ = ['fonction_publique', 'MaClasse'] def fonction_publique(): print("Ceci est une fonction publique") def fonction_privee(): print("Ceci est une fonction privée") class MaClass: def ma_methode(self): print("Méthode de MaClass") class MaClassePrivee: def ma_methode(self): print("Méthode de MaClassePrive")
Dans cet exemple, __all__ contient ['fonction_publique', 'MaClasse'].
Cela signifie que si vous faites from mon_module import *, seuls fonction_publique et MaClasse seront importés, même si les autres fonctions et classes n'ont pas d'underscore.
# autre_module.py from mon_module import * fonction_publique() # Fonctionne correctement # fonction_prive() # Lève une erreur NameError instance = MaClasse() instance.ma_methode() # Fonctionne correctement # instance_prive = MaClassePrive() # Lève une erreur NameError
Mais alors, ça sert à quoi concrètement ?
Sans __all__, Python exporte tous les symboles qui ne commencent pas par un underscore (_).
Cela peut donc devenir problématique si le module contient de nombreux symboles internes qui ne devraient pas être accessibles publiquement.
Voici un exemple de ce que cela donnerai sans utiliser __all__ :
# mon_module_sans_all.py def fonction_publique(): print("Ceci est une fonction publique") def fonction_privee(): print("Ceci est une fonction privée") class MaClass: def ma_methode(self): print("Méthode de MaClass") class MaClassePrivee: def ma_methode(self): print("Méthode de MaClassePrive")
Attention
Avec ce module, l'importation générique expose tous les symboles, car aucun d'eux n'a d'underscore et il n'y a pas de __all__ pour restreindre l'exportation.
# autre_module.py from mon_module_sans_all import * fonction_publique() # Fonctionne correctement fonction_privee() # Fonctionne aussi, même si ce n'était pas voulu instance = MaClasse() instance.ma_methode() # Fonctionne correctement instance_privee = MaClassePrivee() instance_privee.ma_methode() # Fonctionne aussi, même si ce n'était pas voulu
Conclusion
La variable __all__ est un outil précieux pour gérer l'interface publique d'un module Python, permettant de contrôler quelles parties du module sont accessibles via l'importation générique.
Elle aide à maintenir une encapsulation appropriée, à éviter la pollution de l'espace de noms, et à rendre le code plus lisible et maintenable.
En utilisant __all__, vous pouvez mieux structurer vos modules et définir clairement les interfaces publiques !