一 包的介绍
1 什么是包
包就是一个含有__init__.py文件的文件夹
在导包的时候,导入的其实__init__.py文件
包的本质是模块的一种形式
2 为何要有包
随着模块数目的增多,把所有模块不加区分地放到一起也是极不合理的,于是Python为我们提供了一种把模块组织到一起的方法,即创建一个包。
本质是模块,所以用来当作模块导入
二 包的使用
1 导入包与___init___.py
1 首次导入会运行包内__init__文件内的代码
2 产生__init__文件的名称空间,将运行__init__文件时产生的名字都求导该名称空间中
3 在执行文件中得到一个全局名称----包的名字(bag),该名字指向__init__.py文件的名称空间
import bag
print(bag.x) # 相当于__init__.x
from bag import x
print(x)
1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如import 顶级包.子包.子模块,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
2、包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间
3、import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
2 绝对导入与相对导入
Ⅰ 绝对导入(包内导入其他模块)
import sys
print('__init__导入模块的查找顺序')
print(sys.path)
# from import导入
from foo.foo1 import f1
from foo.foo2 import f2
from foo.foo3 import f3
from foo.func.foo4 import f4
在__init__.py文件中导入模块,查找顺序也是参照执行文件的sys.path,即哪个执行文件导了本模块,那么本模块在导入其他模块时查找其他模块的顺序就是参照哪个执行文件的sys.path
大的前提:作为模块的设计者你需要知道,模块的使用者在导入模块的时候,如果模块与执行文件不在同一个文件夹下,使用者一定会将模块所在的文件夹加到sys.path路径中
对设计者来说,在__init__.py文件中导入其他子模块,查找子模块的顺序也是参照执行文件的sys.path,而此时使用者已经将模块的文件夹路径添加到sys.path,所以只需要在sys.path列表中的文件夹中寻找,而使用者在下载模块的时候都是在一个文件夹中的,即模块所在的文件夹是封装好的,所以以包的文件夹作为起始,然后寻找其他子模块,将其他子模块导入到__init__.py中即可,当设计者需要跨文件引用其他包的子模块时,只要将其他包的文件夹路径加入到syspath即可
Ⅱ 相对导入
上述是绝对导入的方式,下面介绍相对导入
相对导入主要用于包内每个子模块的py文件互相引用
.:代表当前文件夹,此时就是foo文件夹
..:代表上一层文件夹
注意:相对导入仅限于包内使用,不能跨出包,否则会出现语法错误
包内的相互导入推荐使用相对导入
from .foo1 import f1
from .foo2 import f2
from .func.foo3 import f3
Ⅲ 两种导入方式对比
两种导入模式的优缺点:
绝对导入:
以顶级的包为起始,点的形式往下找子包,一定能找到
更改包名或着模块名的时候,导入的方式全部要改变
能够导入任意地方的包
相对导入:
包内模块彼此之间的导入,推荐使用相对导入
当对包名更改时,因为只考虑在包内的相对位置
不能跨出包