1.包
引子
为什么要有模块?避免我们重复造轮子,将公共的功能函数集合到一个py文件中,直接import调用。如果一个模块的py文件里面的函数越来越多,一个py文件存储就会冗余,代码量增多。将这个模块分成多个相关模块,将所有的相关功能的模块放置在一个文件夹中,这个文件夹就是包。
什么是包?
包是一个集合了多个相似功能模块的并且含有__init__.py
初始化文件的文件夹。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DmlkPOHE-1664195804517)(//09/26/xVL5Is.png)]
1.1 import 引用包
我们一般是可以执行一个文件的,比如xx.py ,但是一个文件夹是不能执行的。所以,一般我们引用一个包是不会执行这个文件夹。
执行一个模块会发生三件事,引用一个包也会发生三件事。
创建一个以包名命名的名称空间。自动执行初始化文件__init__.py
将这个文件中的所有的变量名加载到包的名称空间。通过包名点的方式引用变量名字。
引用初始化文件中的名字
aaa/__init__.py:name = 'barry'def func():print('in aaa __init__')test.pyimport aaa# print(aaa.name)aaa.func()
引用包中的其他模块的名字
我们只要想通过包引用名字,这个名字一定要出现在__init__.py
######aaa/__init__.py:# import m1"""# 我们引用一个模块名字,这个名字只能出现在三个地方,内存,内置,sys.path,m1 既不在内存,也不是内置,也没有手动添加到sys.path中,所以只是单纯引用m1引用不到的。sys.path会将执行脚本的目录自动添加到sys.path中,执行脚本是test,这个目录下面我们可以直接引用aaa ,所以,我们应用用下面的引用方式。"""from aaa import m1#######aaa/m1.py:age = 18def login():print('登录')######test.pyimport aaaprint(aaa.m1.age)aaa.m1.login()
引用包中的包的__init__.py
的名字
######aaa/__init__.py:from aaa import bbb#######aaa/bbb/__init__.py:hobby = '吃正餐'######test.pyimport aaaprint(aaa.bbb.hobby)
引用包中的包的模块的名字
######aaa/__init__.py:from aaa import bbb#######aaa/bbb/__init__.py:from aaa.bbb import m2#######aaa/bbb/m2.py:def b_func():print('都是科技与狠活呀,兄弟')######test.pyimport aaaprint(aaa.bbb.m2.b_func())
1.2 from import 引用包
前提:通过from import 引用包,基本上就不会使用__init__.py
初始化文件了。
引用包中初始化文件中的名字
aaa/__init__.py:name = 'barry'test.pyfrom aaa import nameprint(name)
引用包中的其他模块的名字
#######aaa/m1.py:age = 18def login():print('登录')#######test.py:# 方式一# from aaa import m1## print(m1.age)# m1.login()# 方式二from aaa.m1 import age, loginprint(age)login()
引用包中的包的__init__.py
的名字
#######aaa/bbb/__init__.py:username = '荣轩'######test.py# 方式一from aaa import bbbprint(bbb.username)# 方式二from aaa.bbb import usernameprint(username)
引用包中的包的模块的名字
#######aaa/bbb/m2.py:def b_func():print('都是科技与狠活呀,兄弟')######test.py# 方式一from aaa.bbb import m2m2.b_func()# 方式二from aaa.bbb.m2 import b_funcb_func()
From … import … 语法
如果我们使用连点操作,点一定出现在import之前,不能使用在import之后。使用这个点,点的左边,一定是一个包。
from … import *
通过from … import * 其实就是将一个模块或者包中的名字全部引用。但是这里有一个小问题,如果是一个包,那么*引用的实际是傀儡文件__init__.py
的所有的名字,因为包作为一个文件夹是不能执行的,只是执行其傀儡文件。
这样,你就可以在傀儡文件__init__.py
中利用之前讲过的__all__
来控制被引用的名字了。
1.3 相对引用、绝对引用
首先我们要知道这样一个前提,无论源码还是第三方或者是我们写的包,都是给我们封装了常用的功能,提供给我们使用的,避免我们重复造轮子。我们在使用这些包的时候,这些包势必会不定期的更新(添加或者更改一些功能),那么这里有一个不成文的原则:无论你这个包如何更新,一定要尽可能的不会影响我之前对你的这个包的使用方式。假如我的项目中有十多处都用了你的包的一些功能,突然有一天你更新了,某些功能原来是通过nb.f1()
进行引用了,但是更新完毕之后变成的new_nb.func1()
,这样的话,我必须将项目中所有的引用方式全部替换,用户体验是极不友好的,那么谁还会用你的功能呢?
版本一
我们创建了一个第三方模块,nb模块,这个模块有两个方法,m1,m2.
# nb.py文件def f1():print('in f1')def f2():print('in f2')# 执行文件.pyimport nbnb.f1()nb.f2()
版本二
随着nb模块封装的功能越来越多,一个文件已经承载不了这么多功能了,我们应该怎么做?我们应该分文件,用到包的思想调整。(我用6个函数比拟600个函数)
# nb包中的傀儡文件`__init__.py`文件from nb.m1 import f1,f2from nb.m2 import f3,f4from nb.m3 import f5,f6# nb包中的m1.py文件def f1():print('in f1')def f2():print('in f2')# nb包中的m2.py文件def f3():print('in f3')def f4():print('in f4')# nb包中的m3.py文件def f5():print('in f5')def f6():print('in f6')# 执行文件.pyimport nbnb.f1()nb.f2()
版本三
这个nb包我只是放在了执行文件的同级目录下,真正的项目中,自定义的包或者第三方的包不会放在你的执行文件的同级目录下面的,而都是统一放在一个文件夹中的,所以我们将nb包的路径更改,放在另一目录中:
import syssys.path.append(r'/Users/barry/PycharmProjects/蒲公英四期/day31/相对导入、绝对导入/lib')import nbnb.f1()nb.f2()nb.f3()nb.f4()nb.f5()nb.f6()
版本四
如果此时我将nb包的名字改成NB了,你应该怎么去做?记住不成文的规定,我们要尽可能少的影响其他人的使用,所以执行文件好改:
import syssys.path.append(r'/Users/barry/PycharmProjects/蒲公英四期/day31/相对导入、绝对导入/lib')import NB as nb # 尽可能少的改动项目中的代码nb.f1()nb.f2()nb.f3()nb.f4()nb.f5()nb.f6()
但是还是报错了, NB模块中的初始化文件报错了:
绝对导入:
绝对导入:以执行文件的sys.path为起始点开始导入,称之为绝对导入
优点: 执行文件与被导入的模块中都可以使用
缺点: 所有导入都是以sys.path为起始点,导入麻烦
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AEAfkvUy-1664195804520)(//09/26/xVO9Rx.png)]
nb 就是我们在sys.path里面主动添加的,只要是从这为起点的导入都是绝对导入。
相对导入
相对导入:参照当前所在文件的文件夹为起始开始查找,称之为相对导入
符号: **. ** 代表当前所在文件的文件夹,
**..** 代表上一级文件夹,**...** 代表上一级的上一级文件夹
优点: 导入更加简单
缺点:只能在导入包中的模块时才能使用
NB/__init__.py:# 绝对导入# from lib.NB.m1 import f1, f2# from lib.NB.m2 import f3, f4# from lib.NB.m3 import f5, f6# 相对导入from .m1 import f1, f2from .m2 import f3, f4from .m3 import f5, f6
如果觉得《包包包包包》对你有帮助,请点赞、收藏,并留下你的观点哦!