38 包介绍

1,434次阅读
没有评论

共计 2025 个字符,预计需要花费 6 分钟才能阅读完成。

一. 什么是包

  • 包就是一个含有 __init__.py 文件的文件夹

  • 包其实就是一个 "超级模块", 用来被导入使用

ps : __init__.py 文件的作用

🍚当你运行一个文件夹的时候, 需要一个文件可以替代文件夹的运行,"__init__.py" 的作用就在于此
🍚在 "python3" 中, 即使包下没有 "__init__.py" 文件, "import" 导入也不会报错, 而在 "Python2" 中, 包下面一定要有该文件
🍚创建包的目的不在于运行, 而是用来被导入使用的, 他就是模块的一种形式, 本质就是模块

二. 为什么用包

  • 当你的功能越来越多, 我们无法把所有的功能都写进同一个文件中去
  • 于是我们使用 模块 组织 功能, 当模块越来越多呢
  • 我们就需要用 文件夹 将模块文件 组织 起来, 以此来提高程序的结构性和可维护性
  • 包就是一个文件夹

三. 使用包的注意事项

  • 包的导入与模块的导入一样使用 from...importimport
  • 导入时 带点 : . 的, 点的左边 必须是一个包, 否则非法, 可以带有一连串的点, 这是导入包特有的语法
  • 使用 from...import 导入时, import后面必须是一个明确的名字, 不能有 任何的前缀

四. 导入包发生的三件事

  • 产生一个包的名称空间
  • 执行包下的 __init__.py 文件, 将产生的名字存放于包的名称空间中
  • 在当前执行文件中拿到一个名字 包文件夹名, 该名字指向包的名称空间
🍚假设我创建一个名为 "aaa" 的包
import aaa   # 导入包 "aaa"

print(aaa.x)  # "aaa.x" 就是向 "__init__.py" 要一个名字 "x"

五. 绝对导入

  • 包里面的导入都是包内模块之间的相互导入, 不是用来执行的
  • 绝对导入都是以包的 顶级路径 作为起始点
  • 绝对导入没有任何限制, 是通用的一种导入方式

1. 一层包示例

38 包介绍

  • 顶级包 : 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. 二层包示例

38 包介绍

  • 顶级包 : 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. 示例

38 包介绍

  • 顶级包 : 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 : 用户无法区分模块是文件还是一个包,我们定义包是为了方便开发者维护

正文完
 
shawn
版权声明:本站原创文章,由 shawn 2023-06-16发表,共计2025字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)