Frage

Ich nehme einmal an, wie das Modellsystem in django Arbeiten und ich bemerkte etwas, das ich nicht verstehe.

Ich weiß, dass Sie eine leere __init__.py Datei erstellen, um festzulegen, dass das aktuelle Verzeichnis ist ein Paket. Und dass Sie einige Variablen in __init__.py festlegen können, so dass import * richtig funktioniert.

Aber django fügt eine Reihe von ... Import ... Aussagen und definiert eine Reihe von Klassen in __init__.py. Warum? Dies nicht nur die Dinge unordentlich aussehen? Gibt es einen Grund, die diesen Code in __init__.py erfordert?

War es hilfreich?

Lösung

Für alle Einfuhren in __init__.py zur Verfügung gestellt werden, wenn Sie das Paket (Verzeichnis) importieren, die es enthält.

Beispiel:

./dir/__init__.py:

import something

./test.py:

import dir
# can now use dir.something

EDIT: vergessen zu erwähnen, der Code in __init__.py läuft das erste Mal, wenn Sie ein beliebiges Modul aus diesem Verzeichnis zu importieren. So ist es normalerweise ein guter Ort für jede Paketebene Initialisierung Code zu setzen.

EDIT2: dgrant wies in meinem Beispiel auf eine mögliche Verwirrung. In __init__.py import something kann ein beliebiges Modul importieren, nicht notwendig aus der Verpackung. Zum Beispiel können wir es mit import datetime, dann in unserem Top-Level-test.py ersetzen diese beiden Schnipsel funktioniert:

import dir
print dir.datetime.datetime.now()

und

import dir.some_module_in_dir
print dir.datetime.datetime.now()

Das Endergebnis ist: alle Namen in __init__.py zugewiesen, seien es importiert Module, Funktionen oder Klassen im Paket Namespace automatisch zur Verfügung steht, wenn Sie das Paket oder ein Modul in dem Paket importieren

.

Andere Tipps

Es ist nur persönliche Präferenz wirklich, und hat mit dem Layout Ihrer Python-Modulen zu tun.

Angenommen, Sie haben ein Modul namens erikutils. Es gibt zwei Möglichkeiten, dass es ein Modul sein kann, haben Sie entweder eine Datei mit dem Namen erikutils.py auf Ihrem sys.path oder Sie haben ein Verzeichnis mit dem Namen erikutils auf Ihrem sys.path mit einem leeren __init__.py Datei in seinem Inneren. Dann lassen Sie uns sagen, Sie haben eine Reihe von Modulen genannt fileutils, procutils, parseutils und Sie wollen, dass die Submodule unter erikutils sein. So einige Py-Dateien machen genannt fileutils.py procutils.py und parseutils.py :

erikutils
  __init__.py
  fileutils.py
  procutils.py
  parseutils.py

Vielleicht haben Sie ein paar Funktionen, die in dem fileutils, procutils oder parseutils Module gehören nicht nur. Und lassen Sie uns sagen, dass Sie nicht das Gefühl, ein neues Modul miscutils genannt wie das Erstellen. AND, Sie möchten in der Lage sein, um die Funktion aufzurufen, etwa so:

erikutils.foo()
erikutils.bar()

anstatt tun

erikutils.miscutils.foo()
erikutils.miscutils.bar()

So, da das erikutils Modul ist ein Verzeichnis, keine Datei, müssen wir definieren, es ist Funktionen innerhalb der __init__.py Datei.

In django, das beste Beispiel, das ich denken kann, ist django.db.models.fields. ALLE django * Feldklassen sind in der definiert __init__.py Datei im django / db / models / Felder Verzeichnis. Ich denke, sie dies taten, weil sie nicht alles in einem hypothetischen stopfen wollte django / db / models / fields.py Modell, so teilten sie es heraus in ein paar Submodule ( verwandt. py, files.py , zum Beispiel), und sie stecken das gemacht * Felddefinitionen in den Bereichen Modul selbst (also __init__.py ).

die __init__.py Datei ermöglicht es Ihnen, die interne Paketstruktur von außen unsichtbar zu machen. Wenn die internen Strukturänderungen (zum Beispiel weil Sie Split ein Fett-Modul in zwei) Sie haben nur die __init__.py Datei anpassen, aber nicht den Code, der von dem Paket abhängt. Sie können auch Teile des Pakets unsichtbar machen, zum Beispiel wenn sie für den allgemeinen Gebrauch nicht bereit sind.

Beachten Sie, dass Sie den del Befehl verwenden können, so ein typisches __init__.py wie folgt aussehen:

from somemodule import some_function1, some_function2, SomeObject

del somemodule

Wenn Sie nun die neuen somemodule __init__.py aufgeteilt entscheiden könnten sein:

from somemodule1 import some_function1, some_function2
from somemodule2 import SomeObject

del somemodule1
del somemodule2

Von außen noch das Paket sieht genauso aus wie vorher.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top