将代码添加到__init__.py

时间:2008-09-23 04:41:18

标签: python initialization package

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

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

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

3 个答案:

答案 0 :(得分:69)

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

示例:

./dir/__init__.py

import something

./test.py

import dir
# can now use dir.something

编辑:忘了提及,__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中分配的所有名称,无论是导入的模块,函数还是类,只要您导入包或程序包中的模块,就可以在程序包命名空间中自动使用。

答案 1 :(得分:34)

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

假设您有一个名为erikutils的模块。它有两种方式可以作为模块,或者在sys.path上有一个名为 erikutils.py 的文件,或者你的目录上有一个名为 erikutils 的目录sys.path内有一个空的 __init__.py 文件。那么假设您有一堆名为fileutilsprocutilsparseutils的模块,您希望这些模块成为erikutils下的子模块。所以你制作一些名为 fileutils.py procutils.py parseutils.py 的.py文件:

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 模型中,所以他们把它分成几个子模块(相关的。 py files.py ,例如)他们将制作的*字段定义粘贴在字段模块本身中(因此, __init__.py )。

答案 2 :(得分:28)

使用__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

从外面看,包裹看起来仍然和以前完全一样。