模块相关
模块简介
在python语言的发展史上,一个相当重要且极其强大的工具绝对占有一席之地,那就是模块,模块我们可以理解为各位大佬提前写好的函数及代码,然后将它们封装在一起,本着前人栽树后人乘凉的宗旨,我们就可以在编写代码的过程中对这些代码进行调用,在实现一些强大功能的同时,简化我们的代码,这也使得python的外号调包侠从贬义转为褒义,让python在IT行业大放异彩
python模块的表现形式:
1.py文件:模块的本质就是写好的代码,存放在特定的python工程文件中,当我们需要使用时就可以调用
2.含有多个py文件的文件夹,当一些py文件中模块的代码功能类似或相近时,我们就可以将它们存放在同一个文件夹下,不同的文件夹代表不同的功能,然后在我们需要使用时去单独调用其中某个文件
3.已被编译为共享库或DLL的c或C++扩展
4.使用C编写并链接到python解释器的内置模块
模块的分类
模块大致可以分为三类
1.自定义模块
即我们自己编写的模块
2.内置模块
python解释器中内置的模块
3.第三方模块
由其他python使用者编写的模块
导入模块的两种句式
在接触模块导入之前,我们需要注意以下几点
- 一定要搞清楚谁是执行文件,谁是被导入文件,否则在模块导入过程中容易出现逻辑混乱
- 以后开发项目的时候py文件的名称一般是纯英文,不会含有中文甚至空格
- 导入模块文件不需要填写后缀名
1.import句式 import关键字加模块名称
import time
import底层原理:
1.先产生执行文件的名称空间
2.执行被导入文件的代码,将产生的名字放入被导入文件的名称空间中
3.在执行文件的名称空间中产生一个模块的名字
4.在执行文件中使用该模块名点的方式使用模块名称空间中所有的名字所以我们才可以使用B加点的方式调用导入文件中的名称
2.from...import...句式 for加导入文件名加import关键字加导入文件中的名称
from B import name
from...import...底层原理
1.先产生执行文件的名称空间
2.执行被导入文件的代码将产生的名字放入被导入文件的名称空间中
3.在执行文件的名称空间中产生对应的名字绑定模块名称空间中对应的名字
4.在执行文件中直接使用名字就可以访问名称空间中对应的名字所以在from...import...句式中可以直接通过名称调用导入文件中的名称
导入模块补充说明
- import与from...import...两者优缺点
import句式:
由于使用模块名称空间中的名字都需要模块名点的方式才可以用
所以不会轻易的被执行文件中的名字替换掉
但是每次使用模块名称空间中的名字都必须使用模块名点才可以
from...import...句式
指名道姓的导入模块名称空间中需要使用的名字 不需要模块名点
但是容易跟执行文件中名字冲突(当执行文件中名称与导入文件中的名称冲突时,执行文件中的名称绑定的数据值会修改掉导入文件中名称所绑定的值)# 执行文件A from B import name name = '张三' print(name) # 导入文件B name = '李四' # 当名称冲突时,导入文件B中name与李四的绑定关系会断开,从而与张三绑定,输出的结果为张三
- 重复导入模块
当我们在执行文件中重复导入同一个模块时,导入命令只会执行一次,不会重复执行
- 别名导入模块
# 我们可以通过别名,将我们所要导入的名字与别名绑定 import B as e # 当我们导入文件时 from B import name as f # 当我们需要导入单个名称时 from B import nameas f, age as d, job as e # 当我们需要导入多个名称时
当我们需要导入多个模块时
import A import B """ 当我们导入的文件中代码作用的相似度不高时,使用上述写法 """ import A, B # 当我们导入的文件中代码作用的相似度较高时,使用左侧写法
循环导入问题
1.循环导入
两个文件之间彼此导入彼此并且相互使用各自名称空间中的名字,这种做法极容易报错
2.如何解决循环导入问题
如果我们不可避免地要使用到这种方式,要确保名字在使用之前就已经准备完毕
如果我们可以避免这种方式出现,那么我们应该尽可能避免出现循环导入
判断文件类型
这里所说的判断文件类型不同于我们之前的数据类型判断
所有的py文件都可以直接打印__name__对应的值
当py文件是执行文件的时候__name__对应的值是__main__
当py文件是被导入文件的时候__name__对应的值是模块名if __name__ == '__main__': print('哈哈哈 我是执行文件 我可以运行这里的子代码') # 利用上述代码我们可以区分它所在文件内代码的执行 # 当模块中出现if __name__ == '__main__':代码时,这个判断条件下的代码不会导入到执行文件中
上述方法多数被使用于程序启动文件中还有模块的开发阶段
from B import * # *默认是将模块名称空间中所有的名字导入,在执行文件中使用 __all__ = ['名字1', '名字2'] # 针对*可以限制导入到执行文件的名字,在导入文件中使用,与*搭配
模块的查找顺序
1.内存中的文件 import aaa import time time.sleep(15) print(aaa.name) aaa.func1() # 即便自定义模块已经导入,但是当我们在运行时删除我们所导入的文件并不影响本次运行,因为在运行过程中,这个文件会被暂时存放在内存中 2.内置 import time print(time) print(time.name) # AttributeError: module 'time' has no attribute 'name' 模块time中没有属性name # 当我们自定义的模块名称与内置模块名称冲突时,会优先执行内置模块 """ 在自定义模块的时候尽量不要与内置模块名冲突 """ 3.执行文件所在的sys.path(系统环境环境) 在这里我们需要强调,一定要以执行文件为准 当我们所要导入的文件在导入时因为系统变量问题报错时 我们可以将模块所在的路径添加到执行文件的系统变量 sys.path 中来解决该问题 import sys print(sys.path) # 列表 sys.path.append(r'D:\pythonProject03\day17\mymd') import ccc print(ccc.name)
相对导入与绝对导入
在相对导入与绝对导入模块,我们需要首先确认执行文件,因为导入的方式都是以执行文件所在的位置为基准
绝对导入 from mymd.aaa.bbb.ccc.ddd import name # 可以精确到变量名 from mymd.aaa.bbb.ccc import ddd # 也可以精确到模块名 ps:规则就是按照项目根目录一层层往下查找 相对导入 .在路径中表示当前目录 ..在路径中表示上一层目录 ..\..在路径中表示上上一层目录 # 不再依据执行文件所在的sys.path,而是以模块自身路径为准 from . import b # 相对导入只能用于模块文件中,不能在执行文件中使用 ''' 相对导入使用频率较低 一般用绝对导入即可 结构更加清晰 '''
包
所谓的包就是含有多个py文件的文件夹
python2中要求文件夹中必须含有__init__.py文件,这个文件夹才会被视为包
而在python3中则没有这样的限制