Добавление кода в init.py
Я смотрю на то, как работает модельная система в django, и я заметил кое-что, что я не понимаю.
Я знаю, что вы создаете пустой __init__.py
файл, чтобы указать, что текущий каталог является пакетом. И что вы можете установить некоторую переменную в __init__.py
Так что импорт * работает правильно.
но Джанго добавляет кучу от ... импорт... операторы и определяет кучу классов в __init__.py
. Зачем? Разве это не заставляет вещи выглядеть грязными? Есть причина, которая требует этот код в __init__.py
?
3 ответа:
все импорт в
__init__.py
становятся доступными при импорте пакета (каталога), который его содержит.пример:
./dir/__init__.py
:import something
./test.py
:import dir # can now use dir.something
EDIT: забыл упомянуть, код в
__init__.py
выполняется при первом импорте модуля из этого каталога. Поэтому обычно это хорошее место для размещения любого кода инициализации на уровне пакета.EDIT2: dgrant указал на возможную путаницу в моем образец. В
__init__.py
import something
можно импортировать любой модуль, не обязательно из пакета. Например, мы можем заменить его наimport datetime
, то в нашем верхнем уровнеtest.py
оба этих фрагмента будут работать:import dir print dir.datetime.datetime.now()
и
import dir.some_module_in_dir print dir.datetime.datetime.now()
итог: все имена, присвоенные в
__init__.py
, будь то импортированные модули, функции или классы, автоматически доступны в пространстве имен пакета при каждом импорте пакета или модуля в пакете.
это просто личные предпочтения на самом деле, и имеет отношение к макету ваших модулей python.
скажем, у вас есть модуль под названием
erikutils
. Есть два способа, что это может быть модуль, либо у вас есть файл с именем erikutils.py на вашемsys.path
или у вас есть каталог с именем erikutils наsys.path
пустой__init__.py
внутри него. Тогда предположим, у вас есть куча модулей под названиемfileutils
,procutils
,parseutils
и вы хотите, чтобы они были подмодулями подerikutils
. Поэтому вы делаете некоторые файлы .py под названием fileutils.py, procutils.py, и parseutils.py:erikutils __init__.py fileutils.py procutils.py parseutils.py
может быть, у вас есть несколько функций, которые просто не принадлежат в
fileutils
,procutils
илиparseutils
модули. И допустим, вам не хочется создавать новый модуль под названиемmiscutils
. И, вы хотели бы иметь возможность вызывать функцию следующим образом:erikutils.foo() erikutils.bar()
а чем занимаюсь
erikutils.miscutils.foo() erikutils.miscutils.bar()
, потому что
erikutils
модуль-это каталог, а не файл, мы должны определить его функции внутри__init__.py
.в django, лучший пример, который я могу придумать это
django.db.models.fields
. Все классы полей django * определены в__init__.py
на django / db / models / fields
С помощью
__init__.py
file позволяет сделать внутреннюю структуру пакета невидимой снаружи. Если внутренняя структура изменяется (например, потому что вы разделили один модуль жира на два), вам нужно только настроить__init__.py
файл, но не код, который зависит от пакета. Вы также можете сделать свой пакет невидимое, например, если они не готовы для общего использования.обратите внимание, что вы можете использовать
del
команда, так что типичный__init__.py
может выглядеть это:from somemodule import some_function1, some_function2, SomeObject del somemodule
теперь, если вы решите разделить
somemodule
новая__init__.py
может быть:from somemodule1 import some_function1, some_function2 from somemodule2 import SomeObject del somemodule1 del somemodule2
снаружи пакета все равно выглядит точно так же, как и раньше.