共计 2025 个字符,预计需要花费 6 分钟才能阅读完成。
一. 什么是包
-
包就是一个含有
__init__.py
文件的文件夹 -
包其实就是一个 "超级模块", 用来被导入使用
ps : __init__.py
文件的作用
🍚当你运行一个文件夹的时候, 需要一个文件可以替代文件夹的运行,"__init__.py" 的作用就在于此
🍚在 "python3" 中, 即使包下没有 "__init__.py" 文件, "import" 导入也不会报错, 而在 "Python2" 中, 包下面一定要有该文件
🍚创建包的目的不在于运行, 而是用来被导入使用的, 他就是模块的一种形式, 本质就是模块
二. 为什么用包
- 当你的功能越来越多, 我们无法把所有的功能都写进同一个文件中去
- 于是我们使用 模块 去组织 功能, 当模块越来越多呢
- 我们就需要用 文件夹 将模块文件 组织 起来, 以此来提高程序的结构性和可维护性
- 包就是一个文件夹
三. 使用包的注意事项
- 包的导入与模块的导入一样使用
from...import
和import
- 在 导入时 带点 :
.
的, 点的左边 必须是一个包, 否则非法, 可以带有一连串的点, 这是导入包特有的语法 - 使用
from...import
导入时,import
后面必须是一个明确的名字, 不能有 任何的前缀
四. 导入包发生的三件事
- 产生一个包的名称空间
- 执行包下的
__init__.py
文件, 将产生的名字存放于包的名称空间中 - 在当前执行文件中拿到一个名字
包文件夹名
, 该名字指向包的名称空间
🍚假设我创建一个名为 "aaa" 的包
import aaa # 导入包 "aaa"
print(aaa.x) # "aaa.x" 就是向 "__init__.py" 要一个名字 "x"
五. 绝对导入
- 包里面的导入都是包内模块之间的相互导入, 不是用来执行的
- 绝对导入都是以包的 顶级路径 作为起始点
- 绝对导入没有任何限制, 是通用的一种导入方式
1. 一层包示例
- 顶级包 : aaa
- 子模块 : xxx.py yyy.py
🍚"__init__.py" 内容
print("i am aaa.__init__") # 包被导入就会被执行
from aaa.xxx import f1
from aaa.yyy import f2
🍚"xxx.py" 内容
def f1():
print("i am xxx")
🍚"yyy.py" 内容
def f2():
print("i am yyy")
🍚"run.py" 内容 # 执行文件
import aaa
aaa.f1()
aaa.f2()
''' 执行结果
i am aaa.__init__
i am xxx
i am yyy
'''
2. 二层包示例
- 顶级包 : aaa
- 顶级包. 子模块 : xxx.py yyy.py
- 子包 : bbb
- 子包子. 模块 : zzz.py
🍚"aaa" 下 "__init__.py" 内容
from aaa.xxx import f1
from aaa.yyy import f2
from aaa.bbb.zzz import f3
🍚"xxx.py" 内容
def f1():
print("i am f1")
🍚"yyy.py" 内容
def f2():
print("i am f2")
🍚"bbb" 下 "__init.py" 内容
from aaa.bbb.zzz import f3
🍚"zzz.py" 内容
def f3():
print("i am f3")
🍚"run.py" 内容 # 执行文件
import aaa
aaa.f1() # 没有改变用户的调用方式
aaa.f2()
aaa.f3()
''' 执行结果
i am f1
i am f2
i am f3
'''
六. 相对导入
- 相对导入只能使用
from...import...
, 使用import .f1
报错 .
代表当前文件所在的目录,..
代表当前文件的上一级目录,...
以此类推- 相对导入不能跨出包, (就是不能
...
点出了顶级包), 仅限于包内模块的相对导入 - 针对 包内部模块 之间的相互导入, 推荐使用相对导入
1. 示例
- 顶级包 : mmm
- 子模块 : m1.py m2.py m3.py
🍚"__init__.py" 内容
from .m1 import f1
from .m2 import f2
from .m3 import f3
🍚"m1.py" 内容
def f1():
print("i am m1.f1")
🍚"m2.py" 内容
def f2():
print("i am m2.f2")
🍚"m3.py" 内容
def f3():
print("i am m3.f3")
🍚"run.py" 内容
import mmm
mmm.f1() # 使用者调用方式不变
mmm.f2()
mmm.f3()
''' 执行结果
i am m1.f1
i am m2.f2
i am m3.f3
'''
七. 绝对导入与相对导入总结
1. 绝对导入
- 以执行文件的
sys.path
为起始点开始导入 - 优点 : 执行文件与被执行的文件中都可以使用
- 缺点 : 所有的导入都是以
sys.path
为起始点, 导入麻烦
2. 相对导入
- 参照当前所在文件的文件夹为起始点开始查找
- 优点 : 导入更加简单
- 缺点 : 只能在包内模块相互导入时才能使用
八.from...import *
*
代表导入所有- 可以使用
__all__=["xxx","yyy"]
来控制能使用的模块 __all__
是在__init__.py
文件下定义的
ps : 用户无法区分模块是文件还是一个包,我们定义包是为了方便开发者维护
正文完