https://www.cnblogs.com/yuanchenqi/articles/5732581.html
https://www.cnblogs.com/xiaoyuanqujing/articles/11640975.html
在计算机程序开发中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护.
为了编写可维护的代码,可以把函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,在Python中一个.py文件称为一个模块
最大的好处是大大提高了代码的可维护性。
其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
所以,模块一共三种:
- python标准库
- 第三方模块
- 应用程序自定义模块
另外,使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。
2.1 import语句
若想在一个.py文件中引入另一个.py文件的功能,需要使用 import 目标模块名,首次导入模块会做三件事:
①执行目标模块中的代码
②产生一个新的名称空间用于存放目标模块执行过程中产生的名字(即目标模块名)
③在当前执行文件所在的名称空间中得到一个名字(即目标模块名),该名字指向新创建的模块名称空间,若想引用模块名称空间的名字,需要加上该前缀,如下:
注:
①当我们使用import语句的时候,Python解释器是怎样找到对应的文件的呢?答案就是解释器有自己的搜索路径,存在sys.path里。
②第一次导入模块已经将其加载到内存空间了,之后的重复导入会直接引用内存中已存在的模块,不会重复执行文件,通过sys模块中的,sys.modules可以看到内存中已经加载的模块名.
③模块名应该遵循小写形式,标准库从python2过渡到python3做出了很多这类调整,如Queue全更新为纯小写模式.
④我们导入的模块中可能包含有python内置的模块,第三方模块,自定义模块,为了便于明显地区分它们,通常在文件的开头导入模块,并且分类导入,不同类别的导入顺序如下:
2.2 from 模块名 import 函数名 as 别名
与import将整个模块导入所不同的是,使用from则是将模块中某一个函数或者名字导入,而不是整个模块,还有一个不同之处是:使用import的导入模块,要使用模块中的函数则必须以模块名加“.”,然后是函数名的形式调用函数;而使用from导入模块中的某个函数,则可以直接使用函数名调用,不用在前面加上模块名称.
此外,使用from导入时,函数名处可以只用一个"*"来表示导入该模块中所有代码,但这种方式会带来一种副作用,即我们无法搞清楚究竟从源文件中导入了哪些名字到当前位置,这极有可能与当前位置的名字产生冲突.模块的编写者可以在自己的文件中定义__all__变量来控制*代表的意思,如下所示:
2.3 循环导入问题
循环导入问题指的是一个模块加载/导入过程中导入另外一个模块,而在另外一个模块中又返回来导入第一个模块中的名字,由于第一个模块尚未加载完毕,所以引用失败.,抛出异常,究其根源就是在python中,同一个模块只会在第一次导入时执行其内部代码,再次导入该模块时,即便是该模块尚未完全加载完毕也不会去重复执行内部代码.
m1.py
m2.py
run.py
测试一
测试二
解决方案
2.4探索模块路径的优先级
模块其实分为四个通用类型,分别是:
①使用纯Python代码编写的.py文件;
②包含一系列模块的包;
③使用C编写并链接到Python解释器中的内置模块;
④使用C或C++编译的扩展模块;
在导入一个模块时,如果该模块已加载到内存中,则直接引用,否则会优先查找内置模块,然后从左往右的顺序依次检索sys.path中定义的路径,直到找到模块对应的文件为止,否则抛出异常.sys.path也被称为模块的搜索路径,它是一个列表类型.
列表中每一个元素都可以当做一个目录来看:在列表中会发现有.zip或.egg结尾的文件,二者是不同形式的压缩文件,事实上Python确实支持从一个压缩文件中导入模块,只需把他们当成目录看即可.
在Python IDLE中执行sys.path,sys.path中第一个路径通常为空,代表执行文件所在的路径,所以在被导入模块与执行文件在同一目录下时肯定是可以正常导入的,而针对被导入的模块与执行文件在不同路径下的情况,为了确保模块对应的源文件仍可以被找到,需要将源文件所在的路径添加到sys.path中,假设foo.py所在的路径为/test/projiects/
2.5 区分py文件的两种用途
一个Python文件有两种用途,一种被当主程序/脚本执行.另一种被当模块导入,为了区别同一个文件的不同用途,每个.py文件都内置了__name__变量,该变量在py文件被当做脚本执行时赋值为"__main__"在py文件被当做模块导入时赋值为模块名
2.6 规范模块的示例