什么是模块
模块就是一系列功能的集合体,在python当中,一个py文件就是一个模块,例如:spam.py 就是一个模块,其中spam就是模块名,可以通过“import spam”来调用
模块主要分为三个部分:
1、内置模块,例如 “time”,“os”等python解释器当中内置
2、自己用python编写的py文件
3、下载别人已经编写好的模块导入自己文件当中(这种拿来主义可以大大提高我们的开发效率)
在我们最开始学习python开始只是使用简单的数据类型和一些流程控制就可以开始编写一些简单的程序,但是这种编写方式在代码量大的情况下就很不方便,后来我们又学习了函数可以将重复的功能定义成函数,通过函数名就可以来重复的调用,但是我们不可能将所有的功能全部都放到一个文件当中,这就需要用到模块,将一些功能分别编写到不同的文件当中,通过import调用,这样从文件级别来组织程序会让程序的条理更加清晰,更加方便管理,也能实现功能的重复利用
import的使用
#模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句)
#test.py import spam #只在第一次导入时才执行spam.py内代码,此处的显式效果是只打印一次‘from the spam.py‘,当然其他的顶级代码也都被执行了,只不过没有显示效果. import spam import spam import spam ‘‘‘ 执行结果: from the spam.py ‘‘‘
import首次导入模块的三道程序:
1、创建一个模块的名称空间
这个名称空间属于全局名称空间一级别的
2、执行模块对应的文件,将产生的名字存放于 “ l ” 的名称空间
3、在当前执行的文件中拿到一个文件名,以该文件名来引用该名称空间
这个名字和变量名没什么区别,与全局变量属于一个级别,且使用spam.名字的方式
可以访问spam.py文件中定义的名字,spam.名字与test.py中的名字来自。
两个完全不同的地方
因为import导入摸块所创建的名称空间属于全局名称空间一级别的,所以我们在导入模块中的名字时不必担心会被执行文件当中的名字冲突掉
为模块起别名
为已经导入的模块起别名的方式对编写可扩展的代码很有用
1 import spam as sm 2 print(sm.money)
有两中sql模块mysql和oracle,根据用户的输入,选择不同的sql功能
# mysql.py def parse(): print(‘hello world‘) # oracle.py def parse(): print(‘HELLO WORLD‘) # 执行文件 # inp=input(‘>>:‘).strip() # if inp==‘mysql‘: # import mysql as db # elif inp==‘oracle‘: # import oracle as db # db.parse()
import导入模块还可以一行导入多个模块
import sys,os,re #(这种方式不建议多用)
from...import
在使用from...import时执行时与import执行前两件事一样
第三步是:在当前名称空间中直接拿到模块中的名字,可以直接使用,不用任何前缀
# from mysql import parse # parse()
优点:使用比import更加方便
缺点:容易与当前执行文件当中的名字产生冲突
在from...import当中与import当中一样支持用 “ as ” 来为模块起别名,一行导入多个模块
当一个模块当中有多样功能的时候,我们可以使用 “ from... import * ”来将模块当中所有不是以下划线开头的全部导入当前位置
但是这种当时的可读性非常差,我们没有办法分清我们导入了哪些名字
这种时候我们可以使用 “ __all__ ” 来控制 “ * ” 的范围
# 在模块中新增一行 __all__=[‘money‘,‘read1‘] #这样在另外一个文件中用from spam import *就这能导入列表中规定的两个名字
模块的查找顺序
1、内存中已经加载的模块
2、内置模块
3、sys.path路径中包含的模块
sys.path的第一个路径是当前执行的文件夹
#模块的查找顺序 1、在第一次导入某个模块时(比如spam),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用 ps:python解释器在启动时会自动加载一些模块到内存中,可以使用sys.modules查看 2、如果没有,解释器则会查找同名的内建模块 3、如果还没有找到就从sys.path给出的目录列表中依次寻找spam.py文件。 #sys.path的初始化的值来自于: The directory containing the input script (or the current directory when no file is specified). PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH). The installation-dependent default. #需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。虽然每次都说,但是仍然会有人不停的犯错。 #在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载。 1 >>> import sys 2 >>> sys.path.append(‘/a/b/c/d‘) 3 >>> sys.path.insert(0,‘/x/y/z‘) #排在前的目录,优先被搜索 注意:搜索时按照sys.path中从左到右的顺序查找,位于前的优先被查找,sys.path中还可能包含.zip归档文件和.egg文件,python会把.zip归档文件当成一个目录去处理, #首先制作归档文件:zip module.zip foo.py bar.py import sys sys.path.append(‘module.zip‘) import foo,bar #也可以使用zip中目录结构的具体位置 sys.path.append(‘module.zip/lib/python‘) #windows下的路径不加r开头,会语法错误 sys.path.insert(0,r‘C:\Users\Administrator\PycharmProjects\a‘) #至于.egg文件是由setuptools创建的包,这是按照第三方python库和扩展时使用的一种常见格式,.egg文件实际上只是添加了额外元数据(如版本号,依赖项等)的.zip文件。 #需要强调的一点是:只能从.zip文件中导入.py,.pyc等文件。使用C编写的共享库和扩展块无法直接从.zip文件中加载(此时setuptools等打包系统有时能提供一种规避方法),且从.zip中加载文件不会创建.pyc或者.pyo文件,因此一定要事先创建他们,来避免加载模块是性能下降。