Domanda

Sto dando un'occhiata a come funziona il sistema modello in django e ho notato qualcosa che non capisco.

So che hai creato un file __init__.py vuoto per specificare che la directory corrente è un pacchetto. E che puoi impostare alcune variabili in __init__.py in modo che import * funzioni correttamente.

Ma django aggiunge una serie di istruzioni from ... import ... e definisce una serie di classi in __init__.py . Perché? Questo non fa semplicemente sembrare le cose disordinate? C'è un motivo che richiede questo codice in __init__.py ?

È stato utile?

Soluzione

Tutte le importazioni in __init__.py sono rese disponibili quando si importa il pacchetto (directory) che lo contiene.

Esempio:

./ dir / __ init __ py .

import something

./ test.py :

import dir
# can now use dir.something

EDIT: dimenticato di menzionare, il codice in __init__.py viene eseguito la prima volta che importi un modulo da quella directory. Quindi è normalmente un buon posto per inserire qualsiasi codice di inizializzazione a livello di pacchetto.

EDIT2: dgrant ha sottolineato una possibile confusione nel mio esempio. In __init__.py importa qualcosa puoi importare qualsiasi modulo, non necessario dal pacchetto. Ad esempio, possiamo sostituirlo con import datetime , quindi nel nostro livello superiore test.py entrambi questi frammenti funzioneranno:

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

e

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

La linea di fondo è: tutti i nomi assegnati in __init__.py , siano essi moduli, funzioni o classi importati, sono automaticamente disponibili nello spazio dei nomi dei pacchetti ogni volta che si importa il pacchetto o un modulo nel pacchetto .

Altri suggerimenti

In realtà è solo una preferenza personale e ha a che fare con il layout dei moduli Python.

Supponiamo che tu abbia un modulo chiamato erikutils . Esistono due modi in cui può essere un modulo: o hai un file chiamato erikutils.py sul tuo sys.path o hai una directory chiamata erikutils sul tuo sys.path con un file __init__.py vuoto al suo interno. Quindi diciamo che hai un sacco di moduli chiamati fileutils , procutils , parseutils e vuoi che siano sotto-moduli in erikutils . Quindi crei alcuni file .py chiamati fileutils.py , procutils.py e parseutils.py :

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

Forse hai alcune funzioni che non appartengono ai moduli fileutils , procutils o parseutils . E diciamo che non hai voglia di creare un nuovo modulo chiamato miscutils . E, ti piacerebbe essere in grado di chiamare la funzione in questo modo:

erikutils.foo()
erikutils.bar()

anziché fare

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

Quindi, poiché il modulo erikutils è una directory, non un file, dobbiamo definire le sue funzioni all'interno del file __init__.py .

In django, il miglior esempio che mi viene in mente è django.db.models.fields . TUTTE le classi di campi django * sono definite nel file __init__.py nella directory django / db / models / fields . Immagino che lo abbiano fatto perché non volevano stipare tutto in un ipotetico django / db / models / fields.py , quindi lo hanno suddiviso in alcuni sottomoduli ( correlati. py , files.py , per esempio) e hanno bloccato le definizioni dei campi * creati nel modulo dei campi stesso (quindi, __init__.py ).

L'uso del file __init__.py ti consente di rendere invisibile la struttura del pacchetto interno dall'esterno. Se la struttura interna cambia (ad es. Perché hai diviso un modulo fat in due) devi solo regolare il file __init__.py , ma non il codice che dipende dal pacchetto. Puoi anche rendere invisibili parti del tuo pacchetto, ad es. se non sono pronti per l'uso generale.

Nota che puoi usare il comando del , quindi un tipico __init__.py potrebbe apparire così:

from somemodule import some_function1, some_function2, SomeObject

del somemodule

Ora se decidi di dividere somemodule il nuovo __init__.py potrebbe essere:

from somemodule1 import some_function1, some_function2
from somemodule2 import SomeObject

del somemodule1
del somemodule2

Dall'esterno il pacchetto sembra ancora esattamente come prima.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top