Estoy echando un vistazo a cómo funciona el sistema modelo en django y noté algo que no entiendo.
Sé que crea un __init__.py
archivo vacío para especificar que el directorio actual es un paquete. Y que puede establecer alguna variable __init__.py
para que la importación * funcione correctamente.
Pero django agrega un montón de declaraciones from ... import ... y define un montón de clases en __init__.py
. ¿Por qué? ¿No hace esto que las cosas se vean desordenadas? ¿Hay alguna razón por la que se requiera este código __init__.py
?
__init__.py
django 1.8. ¿Fue esto para una versión anterior? si es así, ¿qué versión?Respuestas:
Todas las importaciones en
__init__.py
están disponibles cuando importa el paquete (directorio) que lo contiene.Ejemplo:
./dir/__init__.py
:import something
./test.py
:import dir # can now use dir.something
EDITAR: olvidé mencionar, el código se
__init__.py
ejecuta la primera vez que importa cualquier módulo de ese directorio. Por lo tanto, normalmente es un buen lugar para colocar cualquier código de inicialización a nivel de paquete.EDIT2: dgrant señaló una posible confusión en mi ejemplo. En
__init__.py
import something
puede importar cualquier módulo, no es necesario del paquete. Por ejemplo, podemos reemplazarlo conimport datetime
, luego, en nuestro nivel superior,test.py
estos dos fragmentos funcionarán:import dir print dir.datetime.datetime.now()
y
import dir.some_module_in_dir print dir.datetime.datetime.now()
La conclusión es: todos los nombres asignados
__init__.py
, ya sean módulos, funciones o clases importados, están disponibles automáticamente en el espacio de nombres del paquete cada vez que importa el paquete o un módulo en el paquete.fuente
__init__.py
. Realmente no considero el código de inicialización de estas clases (pero tal vez me equivoque al respecto).__init__.py
implícitamente. Al importar los módulos internos__init__.py
, está creando importaciones cíclicas. El__init__.py
no se ejecutará por completo antes de uno de tales importaciones. Es más seguro mantenerlo__init__.py
vacío.__init__.py
archivos. Si tuviera un archivodir/other.py
que tuviera algo comofrom datetime import datetime
, también podría llamardir.other.datetime.now()
o inclusofrom dir.other import datetime
.En realidad, es solo una preferencia personal y tiene que ver con el diseño de sus módulos de Python.
Digamos que tiene un módulo llamado
erikutils
. Hay dos formas en que puede ser un módulo, o tiene un archivo llamado erikutils.py en susys.path
o tiene un directorio llamado erikutils en susys.path
con un__init__.py
archivo vacío dentro. Entonces digamos que usted tiene un montón de módulos llamadosfileutils
,procutils
,parseutils
y que desea que estén bajo submóduloserikutils
. Entonces crea algunos archivos .py llamados fileutils.py , procutils.py y parseutils.py :Tal vez usted tiene algunas funciones que simplemente no tienen cabida en los
fileutils
,procutils
oparseutils
módulos. Y digamos que no tiene ganas de crear un nuevo módulo llamadomiscutils
. Y, le gustaría poder llamar a la función así:en lugar de hacer
Entonces, debido a que el
erikutils
módulo es un directorio, no un archivo, tenemos que definir sus funciones dentro del__init__.py
archivo.En django, el mejor ejemplo en el que puedo pensar es
django.db.models.fields
. TODAS las clases de django * Field se definen en el__init__.py
archivo en el directorio django / db / models / fields . Supongo que hicieron esto porque no querían meter todo en un modelo hipotético de django / db / models / fields.py , por lo que lo dividieron en algunos submódulos ( related.py , files.py , por ejemplo) y pegaron las definiciones de * Field hechas en el módulo de campos en sí (por lo tanto,__init__.py
).fuente
something
puede ser un módulo externo, dir. algo funcionará. Gracias por el comentario, editaré mi publicación para que quede más claro.El uso del
__init__.py
archivo le permite hacer que la estructura interna del paquete sea invisible desde el exterior. Si la estructura interna cambia (por ejemplo, porque divide un módulo fat en dos) solo tiene que ajustar el__init__.py
archivo, pero no el código que depende del paquete. También puede hacer que partes de su paquete sean invisibles, por ejemplo, si no están listas para uso general.Tenga en cuenta que puede usar el
del
comando, por lo que un típico__init__.py
puede verse así:from somemodule import some_function1, some_function2, SomeObject del somemodule
Ahora bien, si decides dividir
somemodule
el nuevo__init__.py
podría ser:from somemodule1 import some_function1, some_function2 from somemodule2 import SomeObject del somemodule1 del somemodule2
Desde el exterior, el paquete todavía se ve exactamente como antes.
fuente
import <pack>.somemodule1
directamente. Solo puede importar desde<pack>
objetos definidos o importados en sus__init__.py
submódulos y no eliminados.