94

我正在研究 django 中的模型系统是如何工作的,我注意到一些我不明白的东西。

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

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

4

3 回答 3

78

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

例子:

./dir/__init__.py

import something

./test.py

import dir
# can now use dir.something

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

EDIT2:dgrant 在我的示例中指出了可能的混淆。in__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无论何时导入包或包中的模块,在包命名空间中分配的所有名称,无论是导入的模块、函数还是类,都会自动可用。

于 2008-09-23T04:47:51.010 回答
39

这只是个人喜好,与你的 python 模块的布局有关。

假设您有一个名为erikutils. 有两种方法可以将它作为一个模块,要么你有一个名为erikutils.py的文件,要么你有一个名为erikutilssys.path目录,里面有一个空文件。然后假设您有一堆名为,的模块,并且您希望它们是 . 下的子模块。因此,您制作了一些名为fileutils.pyprocutils.pyparseutils.py的 .py 文件:sys.path__init__.pyfileutilsprocutilsparseutilserikutils

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

也许您有一些不属于fileutilsprocutilsparseutils模块的功能。假设您不想创建一个名为miscutils. 并且,您希望能够像这样调用该函数:

erikutils.foo()
erikutils.bar()

而不是做

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

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

在 django 中,我能想到的最好的例子是django.db.models.fields. 所有 django *Field 类都在django/db/models/fields目录中的__init__.py文件中定义。我猜他们这样做是因为他们不想把所有东西都塞进一个假设的django/db/models/fields.py模型中,所以他们把它分成几个子模块(例如,related.py 、 files.py)和他们将制作的 *Field 定义固定在 fields 模块本身中(因此,)。__init__.py

于 2008-09-23T06:12:15.080 回答
29

使用该__init__.py文件可以使内部包结构从外部不可见。如果内部结构发生变化(例如,因为您将一个胖模块分成两个),您只需调整__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

从外面看,包装仍然和以前一样。

于 2008-09-24T11:02:55.747 回答