目录
模块
模块基础
模块就是一系列功能的集合体,也就是一堆函数的集合体。因此一个py文件就可以看成一个模块
我们的程序从面条型---》函数版本---》文件版(模块)---》文件夹版(包)
模块的分类
- 自定义模块
- 第三方模块
- 内置模块
- 包
import 与from...import...
我们定义好的模块是拿过来使用的,所以我们可以通过import与from...import...来导入模块
import模块
import time
time.sleep(1)
import导入函数会经过如下三个步骤(以上面函数为例):
- 先到开time模块文件
- python解释器运行time模块,然后把time模块名字放入time模块名称空间
- 主程序中就会有一个变量time指向time模块名称空间
from...import...模块
from time import sleep
sleep(1)
from...import...导入函数会经过如下三个步骤(以上面函数为例):
- 先到开time模块文件
- python解释器运行time模块,然后把time模块名字放入time模块名称空间
- 主程序中就会有一个变量sleep指向time模块名称空间里的sleep函数
循环导入问题
当我们写程序的时候,调用的模块比较频繁,不可避免模块之间的相互调用,这样就有可能出现循环导入问题
# m1.y
from m2 import y
x = 10
# m2.py
from m1 import x
y = 20
如上两个模块之间的相互调用就会出现循环导入问题
- m1文件导入m2文件的y
- m2文件导入m1文件的x
- 因为代码是自上而下运行的,所以在运行m1模块时,会去m2文件找y,但m2模块首先就是去m1模块找x,这样就又回到了m1模块,这样就陷入了循环导入,会报错
解决方案一
# m1.y
x = 10
from m2 import y
# m2.py
y = 20
from m1 import x
将需要调用的放到导入模块之前,这样m1,m2就能找到需要的x,y
但这样做,需要对所有变量都这么做,才能解决问题,没有完美的解决
解决方案二
# m1.y
def f1():
from m2 import y
x = 10
f1()
# m2.py
def f2():
from m1 import x
y = 10
f2()
将模块调用放入到函数中,这样全局变量就会先生成,函数会在文件运行的时候再生成
执行顺序:内置名称空间--》全局名称空间---》局部名称空间
模块的搜索路径
- 去内存中查找
# 验证办法
import m1 # 此时m1模块已在内存空间
import time
# 删除m1模块
time.sleep(10)
import m1 # 此时m1文件已不存在,但不报错,所以是在内存中找到了m1模块
- 去内置模块中找
# 验证办法
# time.py
print('from time')
import time # 无任何打印,证明先去内置模块中找
- 环境变量中找
import sys
print(sys.path)
# b/a/m1.py
# b/test.py
import m1 # 报错
sys.path.append('b/a')
import m1 # 不报错
Python文件的两种用途
- 当作模块文件进行导入,可以有多个
- 当作运行文件,进行文件执行,只能有一个
# m1.py
def f1():
print('from f1')
f1()
# test.py
import m1
m1.f1() # 运行两次
- __name__
# m1.py
def f1():
print('from f1')
if __name__ == '__main__': # __name__在m1.py被当做模块导入时是模块名,作为执行文件时是'__main__'
f1()
# test.py
import m1
m1.f1() # 运行一次
批量生成文件
import compileall
compileall.compile_dir('$dir')
其中,$dir 为Python源代码所在的目录。
包
什么是包
包是模块的一种形式,包的本质就是一个含有__init__.py
的文件的文件夹。
为什么要有包
主要是因为当我们模块太大是,不能更好的去管理,所以可以把这个模块分为多个模块,但我们又不能改变模块的调用方式,就出现了包的概念
如何使用包
导入模块发生的三件事:
- 创建一个包的名称空间
- 执行py文件,将执行过程中产生的名字存放于名称空间中。
- 在当前执行文件中拿到一个名字aaa,aaa是指向包的名称空间的
导入包发生的三件事:
- 创建一个包的名称空间
- 由于包是一个文件夹,无法执行包,因此执行包下的__init__.py文件,将执行过程中产生的名字存放于包名称空间中(即包名称空间中存放的名字都是来自于__init__.py)
- 在当前执行文件中拿到一个名字aaa,aaa是指向包的名称空间的
导入包就是在导入包下的__init__.py,并且可以使用以下两种方式导入:
- import ...
- from ... import...
# aaa.py
def f1():
pass
def f2():
pass
def f3():
pass
def f4():
pass
def f5():
pass
def f6():
pass
def f7():
pass
def f8():
pass
以上aaa模块里面函数看起来就很多,我们把aaa模块分为三个模块
# m1.py
def f1():
pass
def f2():
pass
def f3():
pass
# m2.py
def f4():
pass
def f5():
pass
def f6():
pass
# m3.py
def f7():
pass
def f8():
pass
# aaa/__init__.py
from m1 import *
from m2 import *
from m3 import *
# run.py
from aaa import *
f1()
f2()
...
其实我们在导入aaa时其实是导入的aaa里面的__init__.py
文件,这样我们就做到了在不改变调用方式的情况下把aaa.py模块变成了一个包
注意事项
包内所有的文件都是被导入使用的,而不是被直接运行的
包内部模块之间的导入可以使用绝对导入(以包的根目录为基准)与相对导入(以当前被导入的模块所在的目录为基准),推荐使用相对导入
当文件是执行文件时,无法在该文件内用相对导入的语法,只有在文件时被当作模块导入时,该文件内才能使用相对导入的语法
凡是在导入时带点的,点的左边都必须是一个包,
import aaa.bbb.m3.f3
错误
标签:py,导入,m1,模块,import,def 来源: https://www.cnblogs.com/Hades123/p/11019667.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。