第三方库的设计和演变
包的解释: 含有一个__init__.py文件的文件夹,本质是一个模块,是用来被调用者导入使用的
环境变量参照执行文件所在的文件夹 sys.path
引子
作为包的设计者的角度:
1、设计一个包的话,最初都从单一一个文件,使用的时候 直接 from aaa inport bbb 导入使用
2、每一次更新功能,就要添加代码,要把类型功能的代码整合到其他文件,那么第一条的 from aaa import bbb就不可使用,
在使用者的眼中不能兼容原版本的更新是不可用的。
3、包的功能越来越多,文件越来越多,而相应的调用方式要始终如一 ,如何处理 ?
推导一 __init__文件
回顾 导入模块发生的两件事
1、创建模块的名称空间,运行模块内的代码,把代码中产生的名字放到名称空间内,
2、在当前文件的名称空间中创建一个模块名,指向模块的名称空间
3、思考 上述问题,执行文件只导入一个模块的初始文件,初始文件代码导入该包下所有的模块,使用from aaa.bbb import *
这样的话,功能的名字已经全部被放到aaa的名称空间内,执行文件在aaa的名称空间找到功能了
导入模块就一定会运行一个py文件,一个文件夹也是模块,那么运行的文件就是__init__.py
导入一个包,表面上是把文件夹的内容导入执行文件,其实是在运行 __init__.py
在 __init__.py 写入 x=1
import aaa
print(aaa.x)
如果导入包后,能用aaa.x 找到x的值,那么就证明了确实是运行了 __init__.py 文件
同样的,如果在aaa 目录下新建2个文件m1.py m2.py ,怎么用aaa 找到里面的功能?
from aaa import m1
from aaa import m2
m1.f1()
m2.f2()
以执行文件的环境变量为基准点,m1 和m2 都在aaa目录下,那么aaa和执行文件在同一级目录,
根据查找原则,同目录下文件查找不需要添加环境变量,所以直接from aaa import m1,m2
推导二 能不能把导入的代码放到 init.py文件 ,我只需要导入aaa 就能找到m1 和m2 (aaa目录和执行文件在同一个文件夹下)
分析1:要想使用aaa找到m1 和 m2 就必须把m1 和m2 的名字加入到aaa的名称空间去。
分析2:在执行文件,要想找到aaa的m1和m2 就必须从执行文件的同一级开始找
__init__.py
from aaa import m1
from aaa import m2
import aaa # 在一个目录下导入各个文件
from aaa.bbb import m3 #在 递归目录下,导入各个文件
aaa.m1.f1()
aaa.m2.f2()
aaa.bbb.m3.f3()
推导三 包的文件和执行文件不在同一个目录 aaa包在c盘下,执行文件在d盘下如何导入
import sys
sys.path.append('C:\\111111') # 添加环境变量的路径一定时包名所在的目录,不包括报名,目录之间只用2个\\ 斜线
import aaa
aaa.m1.f1()
推导四 包的绝对导入 、相对导入
包内部导入模块,都是以顶级包名导入,from aaa.bbb import m3 , from aaa import m2
无论是同目录导入还是不同目录的导入,都是因为把包所在的目录加入到了环境变量中(相同目录的已经添加了环境变量),所以才以包名为顶级名
包的顶级文件夹就叫做 绝对导入
包内的互相导入 都是是以顶级包名为起始点导入即可,也叫做绝对导入
对于不同的包的导入 ,也是要使用绝对路径导入,只要该包处于环境变量下即可
包内部的导入
aaa.bbb.m3.py 调用aaa.m2.py的f2功能
aaa.bbb.m3.py的代码
from aaa.m2 import f2
run.py的代码
import aaa
from aaa.bbb import m3
m3.f3()
. 代表当前文件所在的文件夹 .. 上两级目录 ...上三级目录 反正不能出包名
包的init.py
from .m1 import f1
from .m2 import f2
解决 问题
推导结果 包的功能越来越多,文件越来越多,而相应的调用方式要始终如一 ,如何处理 ?
以aaa 这个包为例,aaa包有m1 m2 有个文件,分别有f1 f2 另个功能,如何值导入包名,就能调用功能?
包的init.py
from aaa.m1 import f1
from aaa.m2 import f2
执行文件
import aaa
aaa.f1()
aaa.f2()