1740 Stimmen

Was bedeutet __all__ in Python?

Ich sehe __all__ en __init__.py Dateien. Was wird damit gemacht?

94voto

Bob Stein Punkte 14259

__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 Anweisung from sound.effects import * hace no alle Untermodule aus dem Paket importieren sound.effects in den aktuellen Namespace; es wird lediglich sichergestellt, dass das Paket sound.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]

55voto

Lasse V. Karlsen Punkte 364542

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).

20voto

Cyker Punkte 8424

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__ entonces from foo import * importiert nur Namen, die in foo/__init__.py .

  • (Explizit) Wenn wir definieren __all__ = [] entonces from foo import * wird nichts importiert.

  • (Explizit) Wenn wir definieren __all__ = [ <name1>, ... ] entonces from 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í .

17voto

Mihai Capotă Punkte 1791

__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, wenn from package import * angetroffen wird.

13voto

Eugene Yarmash Punkte 130008

__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?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X