模块的四种形式
一、什么是模块
模块是一系列功能的集合体,而函数是一个功能的集合体,因此模块可以看成是一堆函数的集合体。
一个py文件内部就可以放一堆函数,因此一个py文件就可以看成一个模块。模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。如果这个py文件的文件名为module.py
,则模块名是module
。
模块可以被别的程序引入,以使用该模块中的函数等功能。
二、模块的四种形式
- 自定义模块:如果你自己写一个py文件,在文件内写一堆函数,则它被称为自定义模块,即用python编写的.py文件
- 第三方模块:已被编译为共享库或DLL的C或C++扩展
- 内置模块:使用C编写并链接到python解释器的内置模块
- 包:把一系列模块组织到一起的文件(注:文件夹下有一个
__init__.py
文件,该文件夹被称之为包)
三、为什么要使用模块
- 用第三方或者内置的模块是一种拿来主义,可以极大地提升开发效率。
- 自定义模块,将我们自己程序中用到的公共功能,写入一个python文件,然后程序的各部分组件可以通过导入的方式来引用自定义模块的功能。
- 模块大大的提高可代码的可维护性,编写代码不必从零开始,还避免了函数名和变量名的冲突。
import和form...import
一般使用import和form...import...导入模块
一、import 模块名
import首次导入模块会发生3件事:(以time模块为例)
- 在内存中生成一个叫做time的名称空间
- 运行time.py文件,然后把time.py文件内的名称空间放入time的名称空间内
- 把time的名称空间指向import(当前导入time模块的文件)的名称空间中
使用import time导入的时候,使用方法是:time.方法名(),不能直接调用方法名
二、form 模块名 import 具体的功能
form...import...首次导入模块会发生3件事:(以time模块和time模块中的gmtime()方法为例)
- 在内存中生成一个叫做time的名称空间
- 运行time.py文件,然后把time.py文件内的名称空间放入time的名称空间内
- 把gmtime方法指向form...import(当前导入time模块的文件)的名称空间中
优点:不用加前缀,代码更加精简
缺点:容易与当前执行文件中的名称空间中的名字冲突
# sapm.py
__all__ = ['money','read1'] # 只允许导入'money'和'read1'
# run.py
from spam import * # 导入sapm.py内的所用功能,但会受限于__all__
三、import和form...import的异同
相同点:
- 两者都会执行模块对应的文件,两者都会产生模块的名称空间
- 两者调用功能的时候,需要跑到定义的时候寻找作用域关系,与调用位置无关
不同点:
- import需要加前缀;form...import不需要加前缀
循环导入问题
from m2 import y
print(y)
x = 10
from m1 import x
print(x)
y = 20
不管我们运行第一个代码还是第二个代码都会报错ImportError
(模块导入错误)
模块循环导入抛出异常的原因是由于在python中模块被导入一次后,就不会重新导入,只会在第一次导入时执行模块内代码
解决方法:我们使用函数定义阶段只识别语法的特性解决循环导入的问题,我们也可以从本质上解决循环导入的问题,但是最好的解决方法就是不要出现循环导入。
模块的搜索路径
模块其实就是一个文件,如果要执行文件,首先就需要找到模块的路径(某个文件夹)。如果模块的文件路径和执行文件不在同一个文件目录下,我们就需要制定模块的路径。
模块的搜索路径指的就是在导入模块时需要检索的文件夹。
导入模块时查找模块的顺序是:
- 从内存中寻找
- 内置的模块
- 自定制的模块
- 环境变量(sys.path)中寻找
Python文件的两种途径
python文件总共有两种用途,一种是执行文件,另一种是被当做模块导入:
- 执行文件:一个文件就是整个程序,用来被执行
- 模块文件:文件中存放着一堆功能,用来被导入使用
执行文件和模块文件是相对的
包
一、什么是包
包是一种管理python模块命名空间的形式,采用“点模块名称”。
比如一个模块的名称是A.B,那么它表示一个包A中的子模块B。
包是模块的一种形式,包的本质就是一个含有.py
的文件的文件夹。
包内部只有包含__init__.py
文件,才能被称为包。
就好像使用模块的时候,你不用担心不同模块之间的全局变量相互影响一样,采用点模块名称这种形式也不用担心不同库之前的模块重名的情况。
二、导入包发生的三件事
- 创建一个包的名称空间
- 由于包是一个文件夹,无法执行包,因此执行包下的
.py
文件,将执行过程中产生的名字存放于包名称空间中(即包名称空间中存放的名字都是来自于.py
) - 在当前执行文件中拿到一个名字aaa,aaa是指向包的名称空间的
导入包就是在导入包下的.py
三、绝对导入和相对导入
绝对导入:
以包的根目录为基准
相对导入:
以当前被导入的模块所在的目录为基准
- .代表当前被导入文件所在的文件夹
- ..代表当前被导入文件所在的文件夹的上一级
四、注意事项
- 包内所有的文件都是被导入使用的,而不是被直接运行的
- 包内部模块之前的导入可以使用绝对导入(以包的根目录为基准)与相对导入(以当前被导入的模块所在的目录为基准),推荐使用相对导入
- 当文件是执行文件时,无法在该文件内使用相对导入的语法,只有在文件是被当做模块导入时,该文件内部才能使用相对导入的语法
- 凡是在导入时带点的,点的左边都必须是一个包