在python的模块化中,__init__.py
文件就是模块的入口,它告诉使用者那些功能会被导出和使用。有几种import的方式,每种方式都有它的优点和缺点。
假设一个package中有以下三个模块:
bread.py
def get_bread():
print('A bread.')
coffee.py
def get_coffee():
print('A cup of coffee.')
milk.py
def get_milk():
print('Some milk.')
1. Wild import
如果我们的 __init__.py
是以下的样子:
from .bread import *
from .coffee import *
from .milk import *
那么三个模块中的所有方法或变量都会暴露给外界。使用如下:
import grocery
grocery.get_bread()
总结一下这种模块化的优缺点:
优点
- 可暴露模块的所有功能。
- 可以使用
tab
(自动补全)来查找功能。 - 每一次更新模块功能的时候,不用再去手动修改
__init__.py
文件去包含新添加的功能,因为*
会导入所有的内容。
缺点
- 当这个package大了之后会不好维护,因为你不知道具体都导入了什么东西。
- 需要解决重名问题,例如两个模块同时包含了
print()
函数。
2. Explicit import
如果我们的 __init__.py
是以下的样子:
from .bread import get_bread
from .coffee import get_coffee
from .milk import get_milk
使用这种方法可以只导入你想要暴露的内容。
优点
- 明确想要暴露的内容。
缺点
- 当增加了新功能时,需要去
__init__.py
添加功能的导出。 - 当功能增多的时候,
__init__.py
可能变得很大而不好维护。
3. Export modularly
如果我们的 __init__.py
是以下的样子:
from .bread import get_bread
from .coffee import get_coffee
from .milk import get_milk
如果使用这种方法定义导出的内容,就可以保留package中的模块结构。
import grocery
grocery.bread.get_bread()
优点
- 保留模块结构有利于功能的归类和管理,用户在使用的时候也能更清楚地知道这个功能是从哪个模块引入的。
- 用户可以导入需要的模块,而不是整个package。
-
__init__.py
文件会变得精简。 - 可以解决模块之间重名的问题。
缺点
- 随着package的拓展,结构也会变得复杂。用户需要参照文档来使用。