Ich sehe __all__
en __init__.py
Dateien. Was wird damit gemacht?
Antworten
Zu viele Anzeigen?__all__
passt an *
en from <module> import *
y from <package> import *
.
A Modul ist eine .py
Datei, die importiert werden soll.
A Paket ist ein Verzeichnis mit einem __init__.py
Akte. Ein Paket enthält normalerweise Module.
MODULE
""" cheese.py - an example module """
__all__ = ['swiss', 'cheddar']
swiss = 4.99
cheddar = 3.99
gouda = 10.99
__all__
lässt die Menschen die "öffentlichen" Merkmale einer Modul . [ @AaronHall ] Außerdem werden sie von pydoc erkannt. [ @Langpoke ]
von Modul Einfuhr *
Siehe wie swiss
y cheddar
werden in den lokalen Namensraum gebracht, aber nicht gouda
:
>>> from cheese import *
>>> swiss, cheddar
(4.99, 3.99)
>>> gouda
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'gouda' is not defined
Ohne __all__
wäre jedes Symbol (das nicht mit einem Unterstrich beginnt) verfügbar gewesen.
Einfuhren ohne *
sind nicht betroffen von __all__
importieren Modul
>>> import cheese
>>> cheese.swiss, cheese.cheddar, cheese.gouda
(4.99, 3.99, 10.99)
von Modul importieren Namen
>>> from cheese import swiss, cheddar, gouda
>>> swiss, cheddar, gouda
(4.99, 3.99, 10.99)
importieren Modul como lokaler Name
>>> import cheese as ch
>>> ch.swiss, ch.cheddar, ch.gouda
(4.99, 3.99, 10.99)
PAKETE
In der __init__.py
Datei einer Paket __all__
ist eine Liste von Zeichenketten mit den Namen von öffentlichen Modulen oder anderen Objekten. Diese Merkmale sind für Wildcard-Importe verfügbar. Wie bei Modulen, __all__
passt die *
beim Wildcard-Import aus dem Paket. [ @MartinStettner ]
Hier ist ein Auszug aus der Python-MySQL-Konnektor __init__.py
:
__all__ = [
'MySQLConnection', 'Connect', 'custom_error_exception',
# Some useful constants
'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
'HAVE_CEXT',
# Error handling
'Error', 'Warning',
...etc...
]
Der Standardfall, Sternchen ohne __all__
für ein Paket ist kompliziert, weil das offensichtliche Verhalten teuer wäre: das Dateisystem für die Suche nach allen Modulen im Paket zu verwenden. Stattdessen werden nach meiner Lektüre der Dokumentation nur die Objekte, die in __init__.py
importiert werden:
Si
__all__
nicht definiert ist, wird die Anweisungfrom sound.effects import *
hace no alle Untermodule aus dem Paket importierensound.effects
in den aktuellen Namespace; es wird lediglich sichergestellt, dass das Paketsound.effects
importiert worden ist (und dabei möglicherweise ein Initialisierungscode in__init__.py
) und importiert dann alle Namen, die im Paket definiert sind. Dies schließt alle Namen ein, die durch die folgende Methode definiert wurden (und explizit geladene Untermodule)__init__.py
. Es schließt auch alle Untermodule des Pakets ein, die durch vorherige Importanweisungen explizit geladen wurden.
Und schließlich ist eine verehrte Tradition für Stack-Overflow-Antworten, Professoren und Mansplainers überall, die Bonmot der Vorwurf, überhaupt eine Frage gestellt zu haben:
Wildcard-Importe ... sollten vermieden werden, da sie Leser und viele automatisierte Tools [verwirren].
[ PEP 8 , @ToolmakerSteve]
Desde (Ein inoffizielles) Python-Referenz-Wiki :
Die von einem Modul definierten öffentlichen Namen werden ermittelt, indem im Namensraum des Moduls nach einer Variablen namens
__all__
; falls definiert, muss es sich um eine Folge von Zeichenketten handeln, die von diesem Modul definierte oder importierte Namen sind. Die Namen, die in__all__
werden alle als öffentlich angesehen und müssen existieren. Wenn__all__
nicht definiert ist, umfasst die Menge der öffentlichen Namen alle Namen im Namensraum des Moduls, die nicht mit einem Unterstrich ("_") beginnen.__all__
sollte die gesamte öffentliche API enthalten. Damit soll vermieden werden, dass versehentlich Elemente exportiert werden, die nicht Teil der API sind (wie z. B. Bibliotheksmodule, die importiert und innerhalb des Moduls verwendet wurden).
Kurze Antwort
__all__
betrifft from <module> import *
Erklärungen.
Lange Antwort
Betrachten Sie dieses Beispiel:
foo
bar.py
__init__.py
Unter foo/__init__.py
:
-
(Implizit) Wenn wir nicht definieren
__all__
entoncesfrom foo import *
importiert nur Namen, die infoo/__init__.py
. -
(Explizit) Wenn wir definieren
__all__ = []
entoncesfrom foo import *
wird nichts importiert. -
(Explizit) Wenn wir definieren
__all__ = [ <name1>, ... ]
entoncesfrom foo import *
werden nur diese Namen importiert.
Beachten Sie, dass Python im impliziten Fall keine Namen importieren wird, die mit _
. Sie können jedoch den Import solcher Namen erzwingen, indem Sie __all__
.
Sie können das Python-Dokument einsehen aquí .
__all__
wird verwendet, um die öffentliche API eines Python-Moduls zu dokumentieren. Obwohl es optional ist, __all__
verwendet werden sollte.
Hier ist der entsprechende Auszug aus die Python-Sprachreferenz :
Die von einem Modul definierten öffentlichen Namen werden ermittelt, indem im Namensraum des Moduls nach einer Variablen namens
__all__
; falls definiert, muss es eine Folge von Zeichenketten sein, die von diesem Modul definierte oder importierte Namen sind. Die Namen, die in__all__
werden alle als öffentlich angesehen und müssen existieren. Wenn__all__
nicht definiert ist, umfasst die Menge der öffentlichen Namen alle Namen im Namensraum des Moduls, die nicht mit einem Unterstrich ('_') beginnen.__all__
sollte die gesamte öffentliche API enthalten. Damit soll vermieden werden, dass versehentlich Elemente exportiert werden, die nicht Teil der API sind (wie z. B. Bibliotheksmodule, die importiert und innerhalb des Moduls verwendet wurden).
PEP 8 verwendet einen ähnlichen Wortlaut, obwohl es auch klarstellt, dass importierte Namen nicht Teil der öffentlichen API sind, wenn __all__
abwesend ist:
Um die Introspektion besser zu unterstützen, sollten Module die Namen in ihrer öffentlichen API explizit deklarieren, indem sie die
__all__
Attribut. Einstellung__all__
auf eine leere Liste zeigt an, dass das Modul keine öffentliche API hat.[...]
Importierte Namen sollten immer als Detail der Implementierung betrachtet werden. Andere Module dürfen sich nicht auf den indirekten Zugriff auf solche importierten Namen verlassen, es sei denn, sie sind ein explizit dokumentierter Teil der API des enthaltenden Moduls, wie z. B.
os.path
oder die eines Pakets__init__
Modul, das Funktionen von Untermodulen zur Verfügung stellt.
Außerdem, wie in anderen Antworten erwähnt, __all__
wird verwendet, um die Wildcard-Import für Pakete :
Die Import-Anweisung verwendet die folgende Konvention: Wenn ein Paket die
__init__.py
Code definiert eine Liste namens__all__
ist die Liste der Modulnamen, die importiert werden sollen, wennfrom package import *
angetroffen wird.
__all__
beeinflusst, wie from foo import *
funktioniert.
Code, der sich innerhalb eines Modulkörpers (aber nicht im Körper einer Funktion oder Klasse) befindet, kann mit einem Sternchen ( *
) in einer from
Erklärung:
from foo import *
Le site *
verlangt, dass alle Attribute des Moduls foo
(außer denen, die mit Unterstrichen beginnen) als globale Variablen im importierenden Modul gebunden werden. Wenn foo
hat ein Attribut __all__
ist der Wert des Attributs die Liste der Namen, die durch diesen Typ von from
Erklärung.
Si foo
ist eine Paket und seine __init__.py
definiert eine Liste namens __all__
ist die Liste der Namen der Submodule, die importiert werden sollen, wenn from foo import *
angetroffen wird. Wenn __all__
nicht definiert ist, wird die Anweisung from foo import *
importiert alle Namen, die in dem Paket definiert sind. Dies schließt alle Namen ein, die definiert wurden (und Untermodule, die explizit geladen wurden) durch __init__.py
.
Beachten Sie, dass __all__
muss nicht unbedingt eine Liste sein. Gemäß der Dokumentation über das import
Anweisung falls definiert, __all__
muss ein Folge von Zeichenketten die vom Modul definierte oder importierte Namen sind. Sie können also genauso gut ein Tupel verwenden, um speichern einige Speicher- und CPU-Zyklen. Vergessen Sie nur kein Komma, falls das Modul einen einzigen öffentlichen Namen definiert:
__all__ = ('some_name',)
Siehe auch Warum ist "import *" schlecht?