1.1 模块
1.1.1 模块介绍
常见的场景:一个模块就是一个包含了一组功能的python文件,比如module.py,模块名为module,可以通过import module使用。
模块的三种来源:
1.内置的(python解释器自带的)
2.第三方的(别人写的)
3.自定义的(自己写的)
模块可以分为四个通用类别:
1.使用python编写的py文件(也就意味着py文件也可以称之为模块:一个py文件也可以称之为一个模块)
2.已被编译为共享库或DLL的C或C++扩展(了解)
3.把一系列模块组织到一起的文件夹(文件夹下有一个__init__.py文件,该文件夹称之为包)
包:一系列py文件的结合体
4.使用C编写并连接到python解释器的内置模块
1.1.2 为何要使用模块
1、从文件级别组织程序,更方便管理
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用
2、拿来主义,提升开发效率
同样的原理,我们也可以下载别人写好的模块然后导入到自己的项目中使用,这种拿来主义,可以极大地提升我们的开发效率
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行
#ps:一定要分清楚谁是执行文件谁是被导入文件
sys.path是一个大列表,里面放了一堆文件路径,第一个永远是执行文件所在的文件夹
1.2 使用模块之import
1.2.1 import的使用
模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句),如下
#run.py
1.2.2 在第一次导入模块时会做三件事,重复导入会直接引用内存中已经加载好的结果
1.为源文件(module模块)创建新的名称空间,在spam中定义的函数和方法若是使用到了global时访问的就是这个名称空间。
2.在新创建的命名空间中执行模块中包含的代码,见初始导入import module
提示:导入模块时到底执行了什么?
事实上函数定义也是“被执行”的语句,模块级别函数定义的执行将函数名放入模块全局名称空间表,用globals()可以查看
3.创建名字module来引用该命名空间
这个名字和变量名没什么区别,都是‘第一类的’,且使用module.名字的方式
可以访问module.py文件中定义的名字,module.名字与test.py中的名字来自
两个完全不同的地方。
1.2.3 被导入模块有独立的名称空间
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
1.2.4 为模块名起别名
当模块名字比较复杂的情况下 可以为该函数起别名 如下列情况:
用 as t 为这个不知道有多少个t的文件取个别名
t . 方法还是能够取到testtttttttttttttt.py文件中的值
1.2.5 在一行导入多个模块
import os,time,module(不推荐使用)
特例:
只有当几个模块有相同部分或者属于同一个模块,可以使用上面的方法
当几个模块没有联系的情况下 应该分多次导入
import os
import time
import module
ps:通常导入模块的句式会写在文件的开头
1.2.6 使用模块之from ... import...
1.2.6.1 from ... import... .的使用
#md1.py
#run1.py文件执行结果:
1.2.7 from...import 与import的对比
唯一的区别就是:使用from...import...则是将spam中的名字直接导入到当前的名称空间中,所以在当前名称空间中,直接使用名字就可以了、无需加前缀:module.
#from...import...的方式有好处也有坏处
好处:使用起来方便了
坏处:容易与当前执行文件中的名字冲突
1.2.8 from module import *
#from module import * 一次性把module模块中的名字都加载过来
#大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
#ps: __all__ 方法可以规定导入的数量
如: __all__ = ['money','read1','read2']
1.3 循环导入问题及解决思路
如果出现循环导入问题 那么一定是程序设计的不合理
循环导入问题应该在程序设计阶段就应该避免
解决循环导入问题的方式
1.方式1
将循环导入的句写在载文件最下方()
2.方式2
定义一个函数 函数内导入模块
1.4 py文件区分两种用途:模块与脚本
写好的一个python文件可以有两种用途:
一:脚本,一个文件就是整个程序,用来被执行
二:模块,文件中存放着一堆功能,用来被导入使用
#python为我们内置了全局变量__name__,
当文件被当做脚本执行时:__name__ 等于'__main__'
当文件被当做模块导入时:__name__等于模块名
#作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':
1.5 模块搜索路径
模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
模块的查找顺序
1、在第一次导入某个模块时(比如module),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
ps:python解释器在启动时会自动加载一些模块到内存中,可以使用sys.modules查看
2、如果没有,解释器则会查找同名的内建模块
3、如果还没有找到就从sys.path给出的目录列表中依次寻找module.py文件。
1.6 绝对导入和相对导入
绝对导入:必须依据执行文件所在的文件夹路径为准
绝对导入无论在执行文件中还是被导入文件都适用
相对导入:用.或者..的方式最为起始
1.6.1 绝对导入
1.6.2 相对导入
.代表的当前路径
..代表的上一级路径
...代表的是上上一级路径
注意: 相对导入不能再执行文件中使用
相对导入只能在被导入的模块中使用,使用相对导入 就不需要考虑
执行文件到底是谁 只需要知道模块与模块之间路径关系
1.7 软件开发规范