模块
模块是一系列功能的集合体,而函数是某一个功能的集合体,因此模块可以看成是一堆函数的集合体。
一个py文件内部就可以放一堆函数,因此一个py文件就可以看成一个模块。如果这个py文件的文件名为module.py
,模块名则是module
。
模块的四种来源
- 自定义模块:如果你自己写一个py文件,在文件内写入一堆函数,则它被称为自定义模块,即使用python编写的.py文件
- 第三方模块:已被编译为共享库或DLL的C或C++扩展
- 内置模块:使用C编写并链接到python解释器的内置模块
- 包:把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)
用第三方或者内置的模块可以极大地提升开发效率。
自定义模块,将我们自己程序中用到的公共功能,写入一个python文件,然后程序的各部分组件可以通过导入的方式来引用自定义模块的功能。
导入方式
import
import time
print(time.time()) # 1565853450.5836835
# 模块名.
## 还可以同时导入多个模块
import time,os,sys ## 不过还是建议一个模块使用一个导入语句
from...import...
from random import randint ## 导入random模块中的randint方法,这样做就可以不写模块名
print(randint(1,100)) # 随机产生一个一到一百的整数
print(random) ## 由于只是导入了random模块中的randint方法,所以其他方法是无法调用的
from random import * ## 导入random模块的所有方法,与import类似,只是不需要加模块名
import和from...import...之间的不同点
import 导入模块,每次使用模块中的函数都要是定是哪个模块。
from…import * 导入模块,每次使用模块中的函数,直接使用函数就可以了
循环导入错误
m1.py
from m2 import b
a = 10
print(b)
m2.py
from m1 import a
b = 20
print(a)
无论是从m1开始执行代码还是从m2开始执行代码都会无法从m1/m2找到a/b
这个现象就是一个循环导入错误
python的代码是从文件顶部向底部执行,python的导入对于一个文件只会执行一次。
那么在文件m1的顶部导入了m2,又在文件m2顶部中导入m1。
from m2 import b # m1.py
from m1 import a # m2.py
就举例是从m1.py开始执行程序的:
m1.py执行from m1 import b就暂停m1的代码跳转到m2.py执行代码,m2.py也执行导入m1的语句,又跳转到m1重新开始执行代码,因为python的导入对一个文件只执行一次,所以跳过导入,执行a=10再执行输出b,但是,我们的m2.py文件还没有执行到b=20。所以从这里开始报错,报错没有解决的就一步一步上报这个错误,直到回到m1.py的导入语句,从这里抛出错误,所以才会有无法从m2导入b。
既然知道了原因那么我们就有了解决的办法
方法一:
最简单的直接把导入语句放到需要使用的语句的前一行。
m1.py
a = 10
from m2 import b
print(b)
m2.py
b = 20
from m1 import a
print(a)
方法二:
在函数内导入,不在全局导入
# m1.py
print('from m1.py')
def func1():
from m2 import x
print(x)
y = 'm1'
# m2.py
print('from m2.py')
def func1():
from m1 import y
print(y)
x = 'm2'
模块导入的顺序
- 先从内存中已经导入的模块中寻找
- 内置的模块
- 从自定模块中找
- 环境变量sys.path中找
包
包是模块的一种形式,包的本质就是一个含有.py
的文件的文件夹。
对模块中的函数进行分类并是模块的调用方式不变
由来
假定m1.py文件中有100个函数,我们需要将函数中的函数进行分类存放。于是我们将m1.py文件中的函数分成了三个文件m1.py,m2.py,m3.py 三个文件中。但是,用户不知道不我们将m1分成了三个模块,同时用户也不可能去摸清三个文件中分别都有哪些方法。于是就出现了包。
原理
在导入包的时候是导入包中的__init.py__文件,在__init.py__导入三个文件的所有函数。这样我们表面上就只是导入了一个包,实际上是将这三个文件都导入进来了。