我正在研究 django 中的模型系统是如何工作的,我注意到一些我不明白的东西。
我知道你创建了一个空__init__.py
文件来指定当前目录是一个包。并且您可以设置一些变量,__init__.py
以便 import * 正常工作。
但是 django 添加了一堆 from ... import ... 语句,并在__init__.py
. 为什么?这不是让事情看起来很乱吗?是否有需要此代码的原因__init__.py
?
我正在研究 django 中的模型系统是如何工作的,我注意到一些我不明白的东西。
我知道你创建了一个空__init__.py
文件来指定当前目录是一个包。并且您可以设置一些变量,__init__.py
以便 import * 正常工作。
但是 django 添加了一堆 from ... import ... 语句,并在__init__.py
. 为什么?这不是让事情看起来很乱吗?是否有需要此代码的原因__init__.py
?
__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
无论何时导入包或包中的模块,在包命名空间中分配的所有名称,无论是导入的模块、函数还是类,都会自动可用。
这只是个人喜好,与你的 python 模块的布局有关。
假设您有一个名为erikutils
. 有两种方法可以将它作为一个模块,要么你有一个名为erikutils.py的文件,要么你有一个名为erikutils的sys.path
目录,里面有一个空文件。然后假设您有一堆名为,的模块,并且您希望它们是 . 下的子模块。因此,您制作了一些名为fileutils.py、procutils.py和parseutils.py的 .py 文件:sys.path
__init__.py
fileutils
procutils
parseutils
erikutils
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 *Field 类都在django/db/models/fields目录中的__init__.py
文件中定义。我猜他们这样做是因为他们不想把所有东西都塞进一个假设的django/db/models/fields.py模型中,所以他们把它分成几个子模块(例如,related.py 、 files.py)和他们将制作的 *Field 定义固定在 fields 模块本身中(因此,)。__init__.py
使用该__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
从外面看,包装仍然和以前一样。