Question

Je regarde comment fonctionne le système modèle de Django et j'ai remarqué quelque chose que je ne comprends pas.

Je sais que vous créez un fichier __ init __. py vide pour spécifier que le répertoire en cours est un package. Et que vous pouvez définir une variable dans __ init __. Py afin que l'importation * fonctionne correctement.

Mais django ajoute une série d’instructions ... importées et définit une série de classes dans __ init __. py . Pourquoi? Est-ce que cela ne rend pas les choses plus difficiles? Existe-t-il une raison pour laquelle ce code est requis dans __ init __. Py ?

Était-ce utile?

La solution

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: oublié de mentionner, le code dans __ init __. py est exécuté lors de la première importation d’un module à partir de ce répertoire. C'est donc normalement un bon endroit pour mettre n'importe quel code d'initialisation au niveau du paquet.

EDIT2: dgrant a signalé une confusion possible dans mon exemple. Dans __ init __. Py , quelque chose peut importer n'importe quel module, ce qui n'est pas nécessaire depuis le package. Par exemple, nous pouvons le remplacer par import 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()

La ligne du bas est la suivante: tous les noms attribués dans __ init __. py , qu’il s’agisse de modules, fonctions ou classes importés, sont automatiquement disponibles dans l’espace de noms du package lorsque vous importez le package ou un module dans le package. .

Autres conseils

Il s’agit vraiment de préférences personnelles et de la disposition de vos modules python.

Supposons que vous ayez un module appelé erikutils . Cela peut être un module de deux manières: soit vous avez un fichier nommé erikutils.py sur votre sys.path , soit un répertoire appelé erikutils sur votre sys.path avec un fichier __ init __. py vide. Ensuite, supposons que vous disposiez de plusieurs modules appelés fileutils , procutils , parseutils et que vous souhaitiez que ceux-ci soient des sous-modules sous erikutils . Vous créez donc des fichiers .py nommés fileutils.py , procutils.py et parseutils.py :

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

Vous avez peut-être quelques fonctions qui n'appartiennent tout simplement pas aux modules fileutils , procutils ou parseutils . Et disons que vous n'avez pas envie de créer un nouveau module appelé miscutils . ET vous voudriez pouvoir appeler la fonction comme suit:

erikutils.foo()
erikutils.bar()

plutôt que de faire

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

Comme le module erikutils est un répertoire et non un fichier, nous devons définir ses fonctions dans le fichier __ init __. py .

Dans Django, le meilleur exemple que je puisse penser est django.db.models.fields . TOUTES les classes de champs django * sont définies dans le fichier __ init __. Py du répertoire django / db / models / fields . Je suppose qu’ils ont fait cela parce qu’ils ne voulaient pas tout mettre dans un modèle hypothétique django / db / models / fields.py , ils l’ont donc divisé en quelques sous-modules (liés à . py , fichiers.py , par exemple) et ils ont collé les définitions de * champs définies dans le module de champs lui-même (d'où: __ init __. py ).

L'utilisation du fichier __ init __. py vous permet de rendre la structure de package interne invisible de l'extérieur. Si la structure interne change (par exemple, parce que vous avez scindé un module fat en deux), vous devez uniquement ajuster le fichier __ init __. Py , mais pas le code qui dépend du package. Vous pouvez également rendre certaines parties de votre package invisibles, par exemple. s'ils ne sont pas prêts pour un usage général.

Notez que vous pouvez utiliser la commande del . Ainsi, un __ init __. py typique peut ressembler à ceci:

from somemodule import some_function1, some_function2, SomeObject

del somemodule

Maintenant, si vous décidez de scinder un module , 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 paquet a toujours l'apparence exacte.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top