Ich schaue mir an, wie das Modellsystem in Django funktioniert, und habe etwas bemerkt, das ich nicht verstehe.
Ich weiß, dass Sie eine leere erstellen __init__.py
Datei um anzugeben, dass das aktuelle Verzeichnis ein Paket ist. Und dass Sie eine Variable festlegen können, __init__.py
damit der Import * ordnungsgemäß funktioniert.
Aber django fügt eine Reihe von from ... import ... -Anweisungen hinzu und definiert eine Reihe von Klassen in __init__.py
. Warum? Lässt das die Dinge nicht einfach chaotisch aussehen? Gibt es einen Grund, für den dieser Code erforderlich ist __init__.py
?
__init__.py
Django 1.8. War das für eine ältere Version? wenn ja welche version?Antworten:
Alle Importe in
__init__.py
werden verfügbar gemacht, wenn Sie das Paket (Verzeichnis) importieren, das es enthält.Beispiel:
./dir/__init__.py
::./test.py
::EDIT: vergessen zu erwähnen, den Code in
__init__.py
wenn Sie zum ersten Mal ein Modul aus diesem Verzeichnis importieren. Daher ist es normalerweise ein guter Ort, um Initialisierungscode auf Paketebene einzufügen.EDIT2: dgrant hat in meinem Beispiel auf eine mögliche Verwirrung hingewiesen. In
__init__.py
import something
kann jedes Modul importieren, das nicht aus dem Paket benötigt wird. Zum Beispiel können wir es durch ersetzenimport datetime
, danntest.py
funktionieren in unserer obersten Ebene beide Snippets:und
Das Fazit lautet: Alle in zugewiesenen Namen
__init__.py
, seien es importierte Module, Funktionen oder Klassen, sind automatisch im Paket-Namespace verfügbar, wenn Sie das Paket oder ein Modul in das Paket importieren.quelle
__init__.py
Ich betrachte diesen Klasseninitialisierungscode nicht wirklich (aber vielleicht irre ich mich darin).__init__.py
implizit ausgeführt. Durch den Import der Module im Inneren__init__.py
erstellen Sie zyklische Importe. Das__init__.py
wird vor einem solchen Import nicht vollständig ausgeführt. Es ist sicherer,__init__.py
leer zu bleiben .__init__.py
Dateien ist. Wenn Sie eine Datei hätten,dir/other.py
die so etwas wiefrom datetime import datetime
hätte, könnten Sie auch anrufendir.other.datetime.now()
oder sogarfrom dir.other import datetime
.Es ist wirklich nur eine persönliche Präferenz und hat mit dem Layout Ihrer Python-Module zu tun.
Angenommen, Sie haben ein Modul namens
erikutils
. Es gibt zwei Möglichkeiten, wie es ein Modul sein kann: Entweder haben Sie eine Datei namens erikutils.py auf Ihremsys.path
oder Sie haben ein Verzeichnis namens erikutils auf Ihrem,sys.path
in dem sich eine leere__init__.py
Datei befindet. Dann lassen Sie uns sagen , dass Sie eine Reihe von Modulen haben genanntfileutils
,procutils
,parseutils
und Sie möchten die unter Submodule seinerikutils
. Sie erstellen also einige .py-Dateien mit den Namen fileutils.py , procutils.py und parseutils.py :Vielleicht haben Sie ein paar Funktionen , die einfach nicht , gehören in den
fileutils
,procutils
oderparseutils
Module. Angenommen, Sie möchten kein neues Modul namens erstellenmiscutils
. UND, Sie möchten die Funktion folgendermaßen aufrufen können:anstatt zu tun
Da das
erikutils
Modul also ein Verzeichnis und keine Datei ist, müssen wir seine Funktionen innerhalb von definieren__init__.py
Datei definieren.In django, ist das beste Beispiel , das ich denken kann
django.db.models.fields
. ALLE django * -Feldklassen werden in der__init__.py
Datei im Verzeichnis django / db / models / fields definiert . Ich denke, sie haben dies getan, weil sie nicht alles in ein hypothetisches django / db / models / fields.py- Modell packen wollten , also haben sie es in einige Submodule aufgeteilt ( related.py , files.py zum Beispiel) und Sie haben die gemachten * Felddefinitionen in das Feldmodul selbst gesteckt (daher__init__.py
).quelle
something
sich um ein externes Modul handeln kann, dir.something wird noch funktionieren. Vielen Dank für den Kommentar, ich werde meinen Beitrag bearbeiten, um ihn klarer zu machen.Durch die Verwendung der
__init__.py
Datei können Sie die interne Paketstruktur von außen unsichtbar machen. Wenn sich die interne Struktur ändert (z. B. weil Sie ein Fettmodul in zwei geteilt haben), müssen Sie nur die anpassen__init__.py
Datei , nicht jedoch den Code, der vom Paket abhängt. Sie können auch Teile Ihres Pakets unsichtbar machen, z. B. wenn sie nicht für den allgemeinen Gebrauch bereit sind.Beachten Sie, dass Sie den
del
Befehl verwenden können, sodass ein typischer Befehl folgendermaßen__init__.py
aussehen kann:Wenn Sie sich jetzt entscheiden,
somemodule
das Neue zu teilen,__init__.py
könnte dies sein:Von außen sieht das Paket immer noch genauso aus wie zuvor.
quelle
import <pack>.somemodule1
direkt ausgeführt wird. Sie können nur aus<pack>
Objekten importieren, die in ihren__init__.py
Submodulen definiert oder importiert wurden , sowie aus nicht gelöschten Submodulen.