一、模块化
- 一般来说,编程语言中,库、包、模块是同一种概念,是代码组织方式
- python中只有一种模块对象,但是为了模块化组织模块的便利,提供了一个概念-包、模块是同一种概念,是代码组织方式
- 模块module,指的是python的源代码文件
- 包package,值的是模块组织在一起的和包名同名的目录及其相关文件
二、导入语句
- import 模块1,模块2 : 模块完全导入
- import...as... : 模块别名
1、import语句
- 找到指定的模块,加载和初始化它,生成模块对象,找不到,抛出ImportError异常;在import所在的作用域的局部命名空间中,增加名称和上一步创建的对象关联
import functools # 导入顶级模块 import os.path #导入非顶级模块 print(dir()) print(functools) 导入顶级模块,其名称会加入到本地名称空间中,并绑定到其模块对象 导入非顶级模块,将其顶级模块加入到本地名称空间中,导入的模块必须使用完全限定名来访问 如果使用了as,其后的名称直接加入到本地名称空间中,并直接绑定到导入的模块对象
2、from...import 部分导入
- from...import...as... 别名
- from pathlib import Path,PosixPath # 在当前名称空间导入该模块指定的成员
- from pathlib import * #在当前名称空间导入该模块所有公共成员
- from functools import wraps as wr #别名
举例1: from os.path import exists #加载,初始化os.path模块,exists加入本地名称空间并绑定 if exists('c:\'): print('Found') else: print('Not Found') print(dir()) print(exists) 找到from子句中指定的模块,加载并初始化它 对应import子句后的名称 1、先查form子句导入的模块是否具有该名称的属性 2、如果不是,则尝试导入该名称的子模块 3、还没找到,则抛出ImportError异常 4、这个名称保存到本地名称空间中,如果有as子句,则使用as子句后的名称
三、自定义模块命名规范
- 1、模块名就是文件名
- 2、模块名必须符合标识符的要求,非数字开头的字母数字和下划线的组合
- 3、不要使用系统模块名,避免冲突,除非你明确知道这个模块名的用途
- 4、通常模块名为全小写,下划线来分割
四、模块搜索顺序
1、使用sys.path查看搜索顺序
import sys for p in sys.path: print(p) 执行输出: c:\users\administrator\appdata\local\programs\python\python35\python35.zip c:\users\administrator\appdata\local\programs\python\python35\DLLs c:\users\administrator\appdata\local\programs\python\python35\lib c:\users\administrator\appdata\local\programs\python\python35 c:\users\administrator\appdata\local\programs\python\python35\lib\site-packages c:\users\administrator\appdata\local\programs\python\python35\lib\site-packages\IPython\extensions C:\Users\Administrator\.ipython 显示结果为,python模块的路径搜索顺序,当加载一个模块的时候,需要从这些搜索路径中从前到后依次查找 不搜索这些目录的子目录,搜索到就加载,搜索不到就抛异常
2、路径顺序
- 程序主目录,程序运行的主程序脚本所在的目录
- PYTHONPATH目录,环境变量PYTHONPATH设置的目录也是搜索模块的路径
- 标准库目录,python自带的库模块所在的目录
3、模块的重复导入
- 所有加载的模块都会记录在sys.modules中,sys.modlues存储已经加载过的所有模块的字典,所以不存在重复导入
4、模块运行
- __name__,每个模块都会定义一个__name__特殊变量来存储当前模块的名称,如果不指定,则默认为源代码文件名词,如果是包则有限定名解释器初始化的时候,会初始化sys.modules字典(保存已加载的模块),创建builtins模块,
- __main__模块,sys模块,以及模块搜索路径sys.path
5、if __name__ == '__main__':用途
- 本模块的功能测试,测试本模块内的函数
- 避免主模块变更的副作用,顶层代码没有封装,主模块使用没有问题,但是,一旦有了新的主模块,当前模块要被导入,由于原来代码没有封装,一并执行了
五、模块的属性
- __file__ : 字符串,源文件路径
- __cached__: 字符串,编译后的字节码文件路径
- __spec__ : 显示模块的规范
- __name__ : 模块名
- __package__ : 当模块是包,同__name__,否则,可以设置为顶级模块的空字符串
1、包package特殊的模块
模块和包的总结:
- 包能更好的组织模块,尤其是大模块代码很多,可以拆分成很多子模块,便于使用某些功能就加载相应的子模块;
- 包目录中__init__.py是在包第一次导入的时候就会执行,内容可以为空,也可以是用于该包初始化工作的代码,最好不要删除它;
- 导入子模块一定会加载父模块,但是导入父模块一定不会导入子模块,包目录之间只能使用点作为间隔符,表示模块及其子模块的层级关系
- 模块也是封装,如同类,函数。不过他能够封装变量,类,函数
- 模块就是名称空间,其内部的顶层标识符,都是他的属性,可以通过__dict__或dir()查看
六、绝对导入和相对导入
1、绝对导入
- 在import语句或者from导入模块,模块名称最前面不是以点开头的是绝对导入
- 绝对导入总是去搜索模块搜索路径中找
2、相对导入
- 只能在包内使用,且只能用在from语句中,使用.点号,表示当前目录内
- ..表示表示上一级目录,不要在顶层模块中使用相对导入