1565 votes

Quelqu'un peut-il expliquer __all__ en Python ?

J'utilise de plus en plus Python, et je continue à voir la variable __all__ dans différents __init__.py fichiers. Quelqu'un peut-il expliquer ce que cela fait ?

1412voto

Alec Thomas Points 5815

Lié à cela, mais pas explicitement mentionné ici, est le moment exact où __all__ est utilisé. Il s'agit d'une liste de chaînes de caractères définissant quels symboles d'un module seront exportés lorsque from <module> import * est utilisé sur le module.

Par exemple, le code suivant dans un foo.py exporte explicitement les symboles bar y baz :

__all__ = ['bar', 'baz']

waz = 5
bar = 10
def baz(): return 'baz'

Ces symboles peuvent ensuite être importés comme suit :

from foo import *

print(bar)
print(baz)

# The following will trigger an exception, as "waz" is not exported by the module
print(waz)

Si le __all__ ci-dessus est commenté, ce code s'exécutera alors jusqu'au bout, car le comportement par défaut de l'option import * est d'importer tous les symboles qui ne commencent pas par un trait de soulignement, à partir de l'espace de nom donné.

Référence : https://docs.python.org/tutorial/modules.html#importing-from-a-package

NOTE : __all__ affecte le from <module> import * comportement uniquement. Les membres qui ne sont pas mentionnés dans __all__ sont toujours accessibles depuis l'extérieur du module et peuvent être importés avec la commande from <module> import <member> .

3 votes

Ne devrions-nous pas imprimer baz comme print(baz()) ?

6 votes

@JohnCole baz est un objet fonction et baz() va exécuter l'objet fonction.

0 votes

@BhanuTez exactement. Donc print(baz) imprime quelque chose comme <function baz at 0x7f32bc363c10> alors que print(baz()) imprime baz

830voto

Jimmy Points 35501

C'est une liste d'objets publics de ce module, comme interprété par import * . Il remplace la valeur par défaut qui consiste à masquer tout ce qui commence par un trait de soulignement.

189 votes

Les objets qui commencent par un trait de soulignement, ou qui ne sont pas mentionnés dans la liste des objets de l'UE. __all__ si __all__ est présent, ne sont pas exactement cachés ; on peut les voir et y accéder parfaitement normalement si l'on connaît leur nom. Ce n'est que dans le cas d'un "import *", qui n'est de toute façon pas recommandé, que la distinction a un quelconque poids.

35 votes

@BrandonRhodes : ce n'est pas tout à fait vrai non plus : Il est recommandé de n'importer que les modules dont vous savez qu'ils ont été conçus pour import * (comme par exemple tk ). Un bon indice si c'est le cas est la présence de __all__ ou les noms commençant par un trait de soulignement dans le code du module.

22 votes

Interfaces publiques et internes - python.org/dev/peps/pep-0008/#id50 Pour mieux prendre en charge l'introspection, les modules doivent déclarer explicitement les noms dans leur API publique à l'aide de l'attribut __all__. Le fait de définir __all__ sur une liste vide indique que le module n'a pas d'API publique.

195voto

MartinStettner Points 14514

J'ajoute juste ça pour être précis :

Toutes les autres réponses font référence à modules . La question originale mentionnait explicitement __all__ en __init__.py donc il s'agit de python paquets .

En général, __all__ n'entre en jeu que lorsque le from xxx import * variante de la import est utilisée. Cela s'applique aussi bien aux paquets qu'aux modules.

Le comportement des modules est expliqué dans les autres réponses. Le comportement exact pour les paquets est décrit aquí en détail.

En bref, __all__ au niveau des paquets fait à peu près la même chose que pour les modules, sauf qu'il s'occupe de modules du paquet (contrairement à la spécification de les noms dans le module ). Ainsi, __all__ spécifie tous les modules qui doivent être chargés et importés dans l'espace de noms actuel lorsque nous utilisons le module from package import * .

La grande différence est que, lorsque vous omettre la déclaration de __all__ dans un paquet __init__.py la déclaration from package import * n'importera rien du tout (sauf exceptions expliquées dans la documentation, voir le lien ci-dessus).

D'autre part, si vous omettez __all__ dans un module, le "starred import" importera tous les noms (ne commençant pas par un trait de soulignement) définis dans le module.

32 votes

from package import * importera toujours tout ce qui est défini dans __init__.py même s'il n'y a pas de all . La différence importante est que sans __all__ il n'importera pas automatiquement les modules définis dans le répertoire du paquet.

1 votes

Cuando tous contient [foo, bar] et dans le fichier test.py si nous utilisons : from package import *, alors, est-ce que foo et bar sont importés dans l'espace de noms local de test.py ou dans l'espace de noms propre à foo et bars ?

95voto

Cela change aussi ce que pydoc va montrer :

module1.py

a = "A"
b = "B"
c = "C"

module2.py

__all__ = ['a', 'b']

a = "A"
b = "B"
c = "C"

$ pydoc module1

Help on module module1:

**NAME**
    module1

**FILE**
    module1.py

**DATA**
    **a** = 'A'
    **b** = 'B'
    **c** = 'C'

$ pydoc module2

Help on module module2:

**NAME**
    module2

**FILE**
    module2.py

**DATA**
    **\_\_all\_\_** = \['a', 'b'\]
    **a** = 'A'
    **b** = 'B'

Je déclare __all__ dans tous mes modules, ainsi que de souligner les détails internes, ce qui est très utile lorsque vous utilisez des choses que vous n'avez jamais utilisées auparavant dans des sessions d'interprétation en direct.

56voto

Lasse V. Karlsen Points 148037

Desde Wiki de référence (non officiel) sur Python :

Les noms publics définis par un module sont déterminés en vérifiant l'espace de noms du module pour une variable nommée __all__ ; s'il est défini, il doit être une séquence de chaînes de caractères qui sont des noms définis ou importés par ce module. Les noms donnés dans __all__ sont toutes considérées comme publiques et sont tenues d'exister. Si __all__ n'est pas défini, l'ensemble des noms publics comprend tous les noms trouvés dans l'espace de noms du module qui ne commencent pas par un caractère de soulignement ("_"). __all__ doit contenir l'intégralité de l'API publique. L'objectif est d'éviter d'exporter accidentellement des éléments qui ne font pas partie de l'API (comme les modules de bibliothèque qui ont été importés et utilisés dans le module).

0 votes

Le lien indiqué est mort, mais j'ai trouvé le texte textuel sur le site suivant vdocuments.net/ & ici : dokumen.tips/documents/reference-567bab8d6118a.html

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