🍖包介绍

一.什么是包

  • 包就是一个含有__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.一层包示例

image-20201211154019044

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

image-20201211155416322

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

image-20201211161557717

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

posted @ 2020-12-11 16:40  给你骨质唱疏松  阅读(262)  评论(0编辑  收藏  举报