Je regarde comment fonctionne le système de modèles dans django et j'ai remarqué quelque chose que je ne comprends pas.
Je sais que vous créez un __init__.py
fichier vide pour spécifier que le répertoire actuel est un package. Et que vous pouvez définir une variable __init__.py
pour que l'importation * fonctionne correctement.
Mais django ajoute un tas d'instructions from ... import ... et définit un tas de classes dans __init__.py
. Pourquoi? Est-ce que cela ne rend pas les choses désordonnées? Y a-t-il une raison pour laquelle ce code est requis __init__.py
?
__init__.py
django 1.8. Était-ce pour une version plus ancienne? si oui quelle version?Réponses:
Toutes les importations dans
__init__.py
sont rendues disponibles lorsque vous importez le package (répertoire) qui le contient.Exemple:
./dir/__init__.py
:import something
./test.py
:import dir # can now use dir.something
EDIT: j'ai oublié de mentionner, le code
__init__.py
s'exécute la première fois que vous importez un module de ce répertoire. C'est donc normalement un bon endroit pour mettre tout code d'initialisation au niveau du package.EDIT2: dgrant a signalé une possible confusion dans mon exemple. Dans
__init__.py
import something
peut importer n'importe quel module, pas nécessaire à partir du package. Par exemple, nous pouvons le remplacer parimport datetime
, puis dans notre niveau supérieur,test.py
ces deux extraits fonctionneront:import dir print dir.datetime.datetime.now()
et
import dir.some_module_in_dir print dir.datetime.datetime.now()
En bout de ligne, tous les noms attribués dans
__init__.py
, qu'il s'agisse de modules, de fonctions ou de classes importés, sont automatiquement disponibles dans l'espace de noms du package chaque fois que vous importez le package ou un module dans le package.la source
__init__.py
ne considère pas vraiment le code d'initialisation de ces classes (mais peut-être que je me trompe).__init__.py
implicitement le parent . En important les modules à l'intérieur__init__.py
, vous créez des importations cycliques. Le__init__.py
ne sera pas entièrement exécuté avant une telle importation. Il est plus sûr de rester__init__.py
vide.__init__.py
fichiers. Si vous aviez un fichierdir/other.py
qui contenait quelque chose commefrom datetime import datetime
vous pourriez également appelerdir.other.datetime.now()
ou mêmefrom dir.other import datetime
.C'est juste une préférence personnelle, et cela a à voir avec la disposition de vos modules python.
Disons que vous avez un module appelé
erikutils
. Il y a deux façons dont il peut être un module, soit vous avez un fichier appelé erikutils.py sur votresys.path
ou vous avez un répertoire appelé erikutils sur votresys.path
avec un__init__.py
fichier vide à l'intérieur. Alors disons que vous avez un tas de modules appelésfileutils
,procutils
,parseutils
et vous voulez que ces sous- traiter les modules souserikutils
. Vous créez donc des fichiers .py appelés fileutils.py , procutils.py et parseutils.py :Peut-être vous avez quelques fonctions qui juste ne appartiennent à la
fileutils
,procutils
ou desparseutils
modules. Et disons que vous n'avez pas envie de créer un nouveau module appelémiscutils
. ET, vous aimeriez pouvoir appeler la fonction comme ceci:plutôt que de faire
Donc, comme le
erikutils
module est un répertoire, pas un fichier, nous devons définir ses fonctions à l'intérieur du__init__.py
fichier.Dans django, le meilleur exemple auquel je puisse penser est
django.db.models.fields
. TOUTES les classes de champ django * sont définies dans le__init__.py
fichier du répertoire django / db / models / fields . Je suppose qu'ils l'ont fait parce qu'ils ne voulaient pas tout entasser dans un modèle hypothétique django / db / models / fields.py , ils l'ont donc divisé en quelques sous-modules ( related.py , files.py , par exemple) et ils ont collé les définitions * de champ faites dans le module de champs lui-même (par conséquent,__init__.py
).la source
something
peut être un module externe, dir.quelque chose fonctionnera toujours. Merci pour le commentaire, je modifierai mon message pour le rendre plus clair.L'utilisation du
__init__.py
fichier vous permet de rendre la structure interne du package invisible de l'extérieur. Si la structure interne change (par exemple parce que vous divisez un gros module en deux), vous n'avez qu'à ajuster le__init__.py
fichier, mais pas le code qui dépend du package. Vous pouvez également rendre des parties de votre package invisibles, par exemple si elles ne sont pas prêtes pour une utilisation générale.Notez que vous pouvez utiliser la
del
commande, donc un exemple typique__init__.py
peut ressembler à ceci:from somemodule import some_function1, some_function2, SomeObject del somemodule
Maintenant, si vous décidez de diviser
somemodule
le nouveau__init__.py
pourrait être:from somemodule1 import some_function1, some_function2 from somemodule2 import SomeObject del somemodule1 del somemodule2
De l'extérieur, le colis est toujours exactement comme avant.
la source
import <pack>.somemodule1
directement. Vous ne pouvez importer qu'à partir d'<pack>
objets définis ou importés dans ses__init__.py
sous-modules et non supprimés.