封装包很简单。在文件系统上组织代码,并确保每个目录都定义了init.py文件
(http://upload-images.jianshu.io/upload_images/5404975-b7ee232e7acbb9e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
如果这样做了就可以如下导入文件:
import graphics.primitive.line
from graphics.primitive import line
import graphics.formats.jpg as jpg
文件init.py的目的是
要包含不同运行级别的包的可选的初始化代码。 举个例子,如果你执行了语句import graphics, 文件graphics/init.py将被导入,建立graphics命名空间的内容。像import graphics.format.jpg这样导入,文件graphics/init.py和文件graphics/graphics/formats/init.py将在文件graphics/formats/jpg.py导入之前导入。
绝大部分时候让init.py空着就好。但是有些情况下可能包含代码。 举个例子,
init.py能够用来自动加载子模块:
# graphics/formats/__init__.py
from . import jpg
from . import png
像这样一个文件,用户可以仅仅通过import grahpics.formats来代替import graphics.formats.jpg以及import graphics.formats.png。
敏锐的程序员会发现,即使没有init.py文件存在,python仍然会导入包。如果你没有定义init.py时,实际上创建了一个所谓的“命名空间包”,万物平等,如果你着手创建一个新的包的话,包含一个init.py文件吧。
2.如何控制模块被全部导入的内容
当使用’from module import *‘语句时,希望对从模块或包导出的符号进行精确控制。可以在你的模块中定义一个变量 all 来明确地列出需要导出的内容。
# somemodule.py
def spam():
pass
def grok():
pass
blah = 42
# Only export 'spam' and 'grok'
__all__ = ['spam', 'grok']
尽管强烈反对使用 ‘from module import *‘,但是在定义了大量变量名的模块中频繁使用。
如果你不做任何事,这样的导入将会导入所有不以下划线开头的。 另一方面,如果定义了all ,那么只有被列举出的东西会被导出。如果你将 all 定义成一个空列表,没有东西将被导出。 如果 all 包含未定义的名字,在导入时引起AttributeError。
3.使用相对路径名导入包中子模块
# mypackage/A/spam.py
from . import grok
# mypackage/A/spam.py
from ..B import bar
4.如何合并多个文件合并成一个单一的逻辑命名空间
程序模块可以通过变成包来分割成多个独立的文件。考虑下下面简单的模块
假设你想mymodule.py分为两个文件,每个定义的一个类。要做到这一点,首先mymodule目录来替换文件mymodule.py。 这这个目录下,创建以下文件: