1.模块简介
1.模块的本质:内部具有一定功能(代码)的py文件
2.python模块的历史: python刚开始的时候所有搞其他编程语言的程序员都看不起 甚至给python起了个外号>>>:调包侠(贬义词)
随着时间的发展项目的复杂度越来越高 上面那帮人也不得不用一下python 然后发现真香定律>>>:调包侠(褒义词)
3.python模块的表现形式:
3.1 py文件(py文件也可以称之为模块文件)
3.2 含有多个py文件的文件夹(按照模块功能的不同划分不同的文件夹存储)
3.3 已被编译为共享库或DLL的c或C++扩展(了解)
3.4 使用C编写并链接到python解释器的内置模块(了解)
2.模块的分类
1.自定义模块:我们自己写的模块文件
2.内置模块:python解释器提供的模块
3.第三方模块:别人写的模块文件(python背后真正的大佬)
3.导入模块的两种句式
"""
重点:
1.首先要搞清楚执行文件和被执行文件,如果从文件1中调用了一个模块(文件2),那么文件2是被执行文件,文件1是执行文件
2.开发项目时py文件的名称一般是纯英文
3.导入模块文件(被执行文件)不需要填写后缀名
"""
1.import句式
以import a为例研究底层原理
1.1先产生执行文件的名称空间
1.2执行被导入文件的代码将产生的名字放入被导入文件的名称空间中
(name,age,函数名等)
1.3在执行文件的名称空间中产生一个模块的名字
1.4在该执行文件中使用该模块名点的方式使用模块名称空间中所有的名字(a.name;a.age,a.func()),a就是一个连接执行文件名称空间和模块名称空间的桥梁
2.from...import...句式
以from a import name.func1为例研究底层原理
1.先产生执行文件的名称空间
2.执行被导入文件的代码将产生的名字放入导入文件的名称空间中
3.在执行文件的名称空间中产生对应的名字绑定模块名称空间中对应的名字
4.在执行文件中直接使用名字就可以直接访问名称空间中对应的名字
4.导入模块补充说明
1.import与from...import...两者优缺点
import句式:
模块名称空间中的名字需要模块名点的方式才能使用,所以不会轻易改掉模块名称空间中的名字,需要改的话要将名字前加模块名点的方式。
from...import...句式:
指名道姓地导入模块名称空间中需要使用的名字,不需要模块名点,但是容易跟执行文件中的名字冲突
2.重复导入模块:
解释器只会导入一次,后续重复的导入语句并不会执行
3.起别名:当模块文件名过长时,可以用较短的名字指代,以后通过较短的名字就可以找到模块名称空间中的名字
语法结构1:模块文件名过长:
import 模块文件名 as 缩写模块文件名
语法结构2:模块名称空间中的名字过长:
from b import mingzishibushihenchang as mz
print(mz)
语法结构3:模块名称空间第一个名字过长,后面还有其他名字需要调用: 其他名字直接跟在后面
from b import mingzishibushihenchang as mz, age, hobby
语法结构4:模块名称空间每个名字都很长需要缩写,之久用as连接,排在后面
from b import mingzishibushihenchang as mz, age as a, hobby as h
4.涉及到多个模块导入:
4.1 模块相似度不高:
import b
import buchongshuoming
4.2模块相似度高:
import b, buchongshuoming
5.循环导入问题
1.循环导入:两个文件彼此导入彼此,并且相互使用对方名称空间中的名字,极容易报错。应尽量避免
2.解决方法:
2.1应确保模块名称空间中的名字准备完毕(被执行文件的名字定义在调用模块之前)
2.2应尽量避免循环导入的发生
6.判断文件类型
所有py文件都可以直接打印__name__对应的值
所有py文件都可以打印__name__
1.当py文件是执行文件时,在执行文件中执行print(__name_)_的结果是__main__
2.当py文件是被执行文件时,并且在被执行文件中print(__name__)但不执行,在被导入文件中执行结果是被导入文件的文件名(不加后缀)
执行文件
被执行文件
import md2 # 调用了md2中的模块,证明该文件是执行文件
if __name__ == '__main__':
print('我是执行文件') # 我是执行文件
上述脚本可以用来区分py文件内python代码的执行
使用场景:
1.模块开发阶段
2.项目启动文件
3.用from句式拿到被执行文件中所有的名字:
from a import *,之后就可以拿到名称空间中所有的名字
__all__ = ['名字1', '名字2'] 针对*可以限制拿的名字,也就是执行文件只能取列表中的名字
from语句*可以拿到所有的名字
被限制之后只能拿到列表里面的名字,注意限制的名字要用引号引起来
7.模块的查找顺序
1.内存
import aaa
import time
time.sleep(15)
print(aaa.name)
aaa.func1() # 删掉文件是把硬盘中的删除,内存中的还在
2.内置
"""
自定义模块时尽量不要与内置模块冲突
"""
3.执行文件的sys.path(系统环境变量)
就看sys,path的第一个路径,如果sys.path第一个路径没有要找的模块文件,那么会直接报错
如果想不报错:
那么需要将c.py文件所在的路径添加到sys.path中,此时print(sys.path)会显示增加的c.py的目录路径,此时导入c模块就可以取到c内部的名字。
8.绝对导入和相对导入
"""
要分清导入文件和被导入文件
"""
导入模块时模块文件和导入文件不在同一个目录下解决办法:
1.添加sys.path,但添加被执行文件路径较为麻烦:
sys.path.append(r'被执行文件的绝对路径')
import c
2.也可以使用绝对导入:套路就是按照文件路径一层层网下查找,但是调用c中的名字前面要加c
from aaa.bbb.ccc import c
c.func()
3.相对导入
.在路径中表示当前目录
..在路径中表示上一层目录
..\..在路径中表示上上一层目录
不在依据执行文件所在的sys.path 而是以模块自身路径为准
from . import b
相对导入只能用于模块文件中 不能在执行文件中使用
'''
相对导入使用频率较低 一般用绝对导入即可 结构更加清晰
'''
9.包
通俗来讲就是多个py文件的集合
专业定义:python2中内部含有init、py文件的文件夹,python3中内部含有py文件就叫包
10.包的导入使用
虽然python3对包的要求降低了 不需要__init__.py也可以识别 但是为了兼容性考虑最好还是加上__init__.py(在python3中新建包会自动新建包(python package))
1.如果直接想用包中的某个模块,就直接按昨天绝对路径的方式来找
from aaa.bbb.c import name
print(name)
2.直接导入包名
import aaa
1.导入包名(__init__)后用包名加点,可以使用包里面所有的名字
print(aaa.name)
2.可以使用包下面文件内的名字
print(aaa.md1.age)