将代码添加到__init__.py

Eri*_*rik 84 python initialization package

我正在研究django中的模型系统是如何工作的,我发现了一些我不理解的东西.

我知道你创建一个空__init__.py文件来指定当前目录是一个包.并且您可以设置一些变量,__init__.py以便导入*正常工作.

但是django添加了一堆来自... import ...语句并定义了一堆类__init__.py.为什么?这不是让事情看起来凌乱吗?是否有需要此代码的原因__init__.py

Ale*_*kov 71

__init__.py导入包含它的包(目录)时,所有导入都可用.

例:

./dir/__init__.py:

import something
Run Code Online (Sandbox Code Playgroud)

./test.py:

import dir
# can now use dir.something
Run Code Online (Sandbox Code Playgroud)

编辑:忘记提及,代码在__init__.py第一次从该目录导入任何模块时运行.所以它通常是放置任何包级初始化代码的好地方.

EDIT2:dgrant在我的例子中指出可能存在混淆.在__init__.py import something可以导入任何模块,不需要从包中.例如,我们可以替换它import datetime,然后在我们的顶层test.py,这些片段都可以工作:

import dir
print dir.datetime.datetime.now()
Run Code Online (Sandbox Code Playgroud)

import dir.some_module_in_dir
print dir.datetime.datetime.now()
Run Code Online (Sandbox Code Playgroud)

底线是:__init__.py无论是导入模块,函数还是类,分配的所有名称,无论何时导入包或模块中的模块,都可以在包命名空间中自动使用.

  • 这也可能是出于历史原因.当您将模块转换为包时,module.py到module/__ init__.py所有现有代码都可以像以前一样使用它,但现在模块可以有子模块. (12认同)
  • 好的谢谢。但我仍然不确定为什么将类添加到 `__init__.py` 是一个好主意,我并没有真正考虑这些类的初始化代码(但也许我错了)。 (3认同)

dgr*_*ant 34

这只是个人偏好,而且与你的python模块的布局有关.

假设你有一个名为的模块erikutils.有两种方法,它可以是一个模块,要么你有一个名为erikutils.pysys.path或您有一个目录名为erikutilssys.path用空__init__.py里面的文件.然后让我们说你有一堆模块调用的fileutils,procutils,parseutils和你想那些要承受子模块erikutils.所以你创建了一些名为fileutils.py,procutils.pyparseutils.py的 .py文件:

erikutils
  __init__.py
  fileutils.py
  procutils.py
  parseutils.py
Run Code Online (Sandbox Code Playgroud)

也许你有,只是没有在所属的几个函数fileutils,procutilsparseutils模块.让我们说你不想创建一个名为的新模块miscutils.并且,您希望能够像这样调用函数:

erikutils.foo()
erikutils.bar()
Run Code Online (Sandbox Code Playgroud)

而不是做

erikutils.miscutils.foo()
erikutils.miscutils.bar()
Run Code Online (Sandbox Code Playgroud)

因为erikutils模块是一个目录,而不是一个文件,我们必须在__init__.py文件中定义它的功能.

在django,我能想​​到的最好的例子是django.db.models.fields.所有django*Field类都在django/db/models/fields目录中的__init__.py文件中定义.我猜他们这样做是因为他们不希望所有东西都塞进一个假想的Django/DB /模型/ fields.py模式,所以他们分裂出来成几个子模块(related.py,files.py,例如)和他们将制作的*字段定义粘贴在字段模块本身中(因此).__init__.py


nik*_*kow 29

使用该__init__.py文件可以使内部包结构从外部不可见.如果内部结构发生变化(例如,因为您将一个胖模块拆分为两个),您只需要调整__init__.py文件,而不是依赖于包的代码.您也可以使包的一部分不可见,例如,如果它们还没有为一般用途做好准备.

请注意,您可以使用该del命令,因此典型的__init__.py可能如下所示:

from somemodule import some_function1, some_function2, SomeObject

del somemodule
Run Code Online (Sandbox Code Playgroud)

现在,如果您决定拆分somemodule新的__init__.py可能是:

from somemodule1 import some_function1, some_function2
from somemodule2 import SomeObject

del somemodule1
del somemodule2
Run Code Online (Sandbox Code Playgroud)

从外面看,包装看起来仍然像以前一样.

  • @Arlen:删除模块会直接阻止`import <pack> .somemodule1`.您只能从`__init __.py`中定义或导入的`<pack>`对象和未删除的子模块导入. (5认同)

joe*_*tz1 7

\n

“不过,我们建议不要在 \xc2\xa0 __init__.py\xc2\xa0 文件中放入太多代码。程序员并不期望在此文件中发生实际逻辑,并且与 \xc2\xa0 非常相似,from x import *如果他们正在查找,可能会绊倒他们对于特定代码段的声明,在检查\xc2\xa0 之前无法找到它__init__.py。”

\n

——Python 面向对象编程第四版 Steven F. Lott Dusty Phillips

\n
\n