包和模块
模块
什么是模块?
- 随着程序的功能越多,代码量越多。显然放一个文件不容易维护,为了编写可维护的代码。可以把函数分组,一个函数就是一个模块。
- 在Python中,一个py文件就是一个模块(module)
使用模块有什么好处
- 大大提高了代码的可维护性
- 可以避免函数名和变量名冲突,每个模块有自己独立的名称空间。
分类
- 内置模块:help(modules)可查看内置模块列表
- 第三方模块:pip install module 联网安装
- 自定义模块
模块调用
- 一旦调用模块,相当于执行了模块里的代码
import os
import time, json
from decimal import Decimal
from decimal import Decimal as d
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import *
- 模块查找路径:python解释器会按照列表顺序依次每个目录去匹配你要导入的模块名,匹配到了就不会往后找。
import sys
print(sys.path)
包
包是一种管理 Python 模块命名空间的形式,采用"点模块名称"。
比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B 。
就好像使用模块的时候,你不用担心不同模块之间的全局变量相互影响一样,采用点模块名称这种形式也不用担心不同库之间的模块重名的情况。
这样不同的作者都可以提供 NumPy 模块,或者是 Python 图形库。
包的创建
创建包会自动生成__init__.py
文件
![1561980301880](file:///C:/Users/86131/AppData/Roaming/Typora/typora-user-images/1561980301880.png)
回忆 创建一个tbjx模块发生的三件事:
将该tbjx文件加载到内存.
创建一个以tbjx命名的名称空间.
通过tbjx. 的方式引用tbjx模块的所有的名字.
创建一个包,也会发生三件事:
将该aaa包内 __init__py文件加载到内存.
创建一个以aaa命名的名称空间.
通过aaa. 的方式引用__init__的所有的名字.
包名就是 幕后指使的 init执行
包的引用方式
import 方式导入
aaa包与执行文件同级的情况
引用aaa包的__init__中的name
import aaa
print(aaa.name)#因为执行aaa 其实就是执行__inint__中内容
# 我想要引用 aaa包的m1文件的a变量
# 错误示例1:
import aaa
# 1. aaa的 __init__ 里面 写import m1
# 2. print(aaa.m1.a)
# print(aaa.m1.a)
# 报错原因: No module named 'm1'
# 分析报错原因: 模块找不到 内存,内置,sys.path三个地方找不到.
# m1 不在内存,不在内置,sys.path 会主动加载执行文件(包的使用.py)的当前目录. 而他不在
# 解决方式:
import aaa
# 1. 在执行文件写入 import aaa
# 2. aaa的 __init__ 里面 写 from aaa import m1#m1是要引入的文件名 aaa是包名
# 3. 然后在执行文件 aaa.m1.a
# print(aaa.m1.a) 引用 aaa包的m1的a
# print(aaa.m1.func1())#引用 aaa包的m1的func1()
# 如何在当前文件中,引用 aaa包的bbb包中__init__中 name.
# 1. 在执行文件写入 import aaa
# 2. aaa的 __init__ 里面 写 from aaa import bbb
# 3. 然后在执行文件 print(aaa.bbb.name)
# 如何在当前文件中,引用 aaa包的bbb包 a1.py文件中的 name
# 1. 在执行文件写入 import aaa
# 2. 在aaa包的__Init__ 写上 from aaa import bbb (这样写 bbb包的__init__里面所有的名字都能引用)
# 3. 在bbb包的__Init__ 写上 from aaa.bbb import mb
4 print(aaa.bbb.a1.name)
# 首先 无论从哪里引用模块,import 或者 from ... import ...
# 最开始的模块或者包名一定是内存,内置,sys.path中能找到的.(可参考bbb包中的 __init__)
# 直接import 为了让我们会使用 包里面的 __init__
from方式导入
# 第二类: 执行文件 通过 from ... import... 导入包以及包内的功能
# from ... import ...
# 通过这种方式不用设置__init__文件
我想要引用 aaa包的__init__ name
from aaa import name
print(name)
我想要引用 aaa包的 a1 文件中name
from aaa import a1
print(a1.name)
我想要引用 aaa包的 bbb包 __init__ name
from aaa.bbb import name
print(name)
我想要引用 aaa包的 bbb包 a1文件的中的name
from aaa.bbb import a1
print(a1.name)
重点
# from a.b.c import d
# c的. 的前面一定是包
# import 的后面一定是名字 可以是文件, 并且不能 再有点 不能有点
# from aaa.bbb.m2.func1 import a # 错误的
# from aaa.bbb import m2
# m2.func1()
相对导入与绝对导入
# from nb.m1 import f1,f2
# from nb.m2 import f3,f4
# from nb.m3 import f5,f6
# 目前为止,今天所看到的引用模块的方式都是绝对导入
# 相对导入: . .. ......
from .m1 import f1,f2
from .m2 import f3,f4
from .m3 import f5,f6
from .dsb.ly import f7
需求
# 由于nb模块增加了很多很多功能,所以我们nb这个文件就要划整一个包,
# 无论对nb模块有任何操作,对于使用者来说不应该改变,极少的改变对其的调用. 像装饰器
第一版 文件变成包了 包与执行文件 在同一目录
用户 使用方式
# import nb
# nb.f1()
# nb.f2()
我们的解决方式 在aaa包的__init__ 加入
from nb.m1 import f1,f2#m1 中有f1 f2
from nb.m2 import f3,f4
from nb.m3 import f5,f6
第2版 包与 执行文件 不在同一文件 要想运行 必须在执行文件 添加sys 路径
import sys
sys.path.append(r'D:python22python 23 代码day19相对导入第2版 包在另一个文件下dir') #写死了 可以动态传
第3版 模块改名
在__init__ 里面改成相对导入
from .m1 import f1,f2#当前目录上一级
from .m2 import f3,f4
from .m3 import f5,f6
from .. import settings