包概述
一个.py
文件就是一个模块, 但是模块一多, 管理起来也是比较麻烦.
python 提供包是为了更好的对模块进行管理.
包可以看做是一组模块的集合, 把这组模块放在一个包的名称下.包这项技术可以解决不同的应用程序之间模块的命名冲突问题.
一个包包括两个必要条件:
一个文件夹. 这个文件夹的名字其实就是包的名字.包的命名规则和公共模块的命名一致:全部字符小写, 不同的单词之间用下划线连接.
在上述文件夹下的一个
__init__.py
的初始化文件. 这个文件可以为空, 也可以定义一些导入模块时候的初始化代码.
注意:
一个包中可以有自己的子包, 子包也可以再有子包... 每一个包都会有一个自己的__init__.py
文件.
从包中导入模块
定义包是为了更好的管理模块, 有几种导入模块的方式!
假设有这样的一个包结构:
使用import
导入模块
# 导入 echo 模块
import sound.effects.echo
# 使用的时候必须使用全名
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
使用from
导入模块
# 导入 echo 模块
from sound.effects import echo
# 只需要包名即可
echo.echofilter(input, output, delay=0.7, atten=4)
使用from
直接导入模块中的定义
# 从模块中导入定义
from sound.effects.echo import echofilter
# 直接调用导入的函数即可
echofilter(input, output, delay=0.7, atten=4)
注意:
当我们多个模块中都导入同一个模块的时候, 只有第一次导入的时候才会执行包的__init__()
和模块中的代码.
可以这样理解: 当导入某个模块的时候, 会先查找某个模块是否已经到过, 如果已经导入过, 就直接使用不再重新导入.
使用*
通配符导入
使用from 包 import *
, 可以导入整个包下所有的模块.
但是由于各个操作系统的在对文件名的命名上的差异, 默认情况下这个语句一个包都导入不了.
我们可以在这个包的__init__.py
定义一个列表, 这个列表中定义使用*
的时候可以导入哪些包
__all__ = ["a", "b"] # 使用 * 的时候导入a 和 b 两个包
使用相对导入
同一个包下的模块互相导入的时候, 也需要些完全限定名, 也就是把他们的上级的所有的包都要写上, 这是比较麻烦的.
所以, python 还是支持一种相对导入.
一个点.
表示当前包, 两个点..
表示表示父包
相对导包只能用在from
中.
from . import my2
注意:
相对导包的原理是根据当前模块的__name__
来计算的包的路径, 由于主模块的__name__
值永远是__main__
, 所以主模块中不能使用相对导包, 只能使用绝对路径去导包.