之前我们在学习中,我们写的python都是只需要放在一个文件,内容较少
但是在实际的项目中,代码量可能非常大,可能几十万行代码都有可能,这样放在一个文件中显然不合适
为了编写可维护的代码,我们把代码安装功能点分割出来,分别放到不同的文件里,这样,每个文件包含的代码相对较少
基本上大部分编程语言都编程语言都采用这种组织代码方式
在python中,代码是放在py为扩展名的文件中,一个.py文件就称之为一个模块(Module)
我们又可以把许多模块按照功能放大不同的目录中来组织。这些组织存放模块文件的目录,我们称之为包(Package)
6.1模块和包的作用
为什么要使用模块和包呢?
首先,它大大提高了代码的可维护性。一个模块可以引用另一个模块里面的对象(包括数据和函数)。我们在编写程序的时候,
经常引用其他模块,包括我们自己写的模块,python内置的模块,还有后来安装的第三方模块。
其次,使用模块还可以避免函数名和变量名冲突,可以想象,如果一个代码文件特别的大,实现很多功能,难免其中有些变量的名字会发生重复。这时候我们要绞尽脑汁想出不同的变量名或者函数名。如果采用模块分割代码,每个模块文件代码都不是很多,就可以大大的缓解这个问题
6.2.自定义模块
假设我们需要将一个计算数字平方和立方的函数,放到一个模块calc.py里面,其内容如下:
var1 = 20 def calc_s(num): print('square of num is %s' % num**2) def calc_s(num): print('cube of num is %s' % num**3) def calc_s_c(num): print('square of num is %s' % num**2) print('cube of num is %s' % num**2)
现在我们要在别的模块里面使用该模块里面的calc_s_c函数,该怎么做呢?
在使用别的模块里面的变量和函数时,首先需要把它们“弄”到当前模块来,需要用到import这个关键字
import calc cal.calc_s_c(10)
上面这种方法就是把calc模块对象(注意 模块在python中也是对象)导入到当前模块中了,并且当前模块中还是用calc这个变量
指向该模块。这里模块名就是文件名(不需要扩展名.py)
当然,我们也可以用另一种方式
from calc import calc_s_c calc_s_c(10)
这样就把calc模块里面的calc_s_c函数对象(注意:python中,函数也是对象)导入到当前模块中,并且当前模块中还是要用calc_s_c这个变量指向该函数对象
那如果我们除了要使用calc_s_c,还要使用calc_s,可以这样
from calc import calc_s_c,calc_s cals_s_c(10) cals_s(10)
同样的,我们导入模块的时候,可以多个模块一起导入,例如:
import modeule1,modue2,modul3
上面的例子还要个偷懒的方法
from calc import * calc_s_c(10) calc_s(10)
这里import * 把calc模块所有可以导入的对象全部都导入了。包括calc_s_c,calc_s,calc_c函数,还要那个变量var1
我们在导入对象的时候,还可以把导入对象原来的变量名字改掉
import calc as c c.calc_s_c(10)
from calc import calc_s_c as sc sc(10)
6.3.自定义包
当项目比较大的时候,往往光有自定义模块还是不够的,想象一下,在一个目录下放置几十上百的模块文件是多么乱
所以,python允许我们将功能相关的模块放到相应的目录结构中来组织模块。这些组织存放模块文件的目录,我们称之为包(Package)
但是python要求这些包目录一定要有一个特别的文件__init__.py,在里面
下面是一个Package目录结构的例子
Phone/ __init__.py common_util.py voicedta/ __init__.py post.py isdn.py Fax/ __init__.py G3.py
Mobile/
__init__.py
Analog.py
Digital.py
Pager/
__init__.py
Numeric.py
Phone是最顶层的package而Voicedta,Fax,Mobile,Pager都是子package。导入子packages,导入子packages,可以这样写
import Phone.Mobile.Analog Phone.Mobile.Analog.dial()
当然也可以使用from...import...的方式,下面这几种方式的使用都可以
from Phone.Mobile import Analog Analog.dial('30')
from Phone.Mobile.Analog import dial dial(323)
在范例的目录结构里面。__init__.py文件是初始化文件。在我们使用from-import语句的时候,会执行里面的代码。它是必须要存在的
,即使没有初始化工作要做,也必须有这个空文件
6.4.使用内置模块
之所以用python可以比其他语言写出更加简洁的代码,一个原因是python高层抽象的简洁的语法,另一个重要原因就是其丰富
的内置库和海量优秀的第三方库。
内置模块就是python安装的时候就提供的功能模块和包,python以及贴心的帮我妈把程序设计中常用的功能都做好了,放在内置库
我们只需要导入就可以使用。
例如:我们需要获取系统当前时间,只需要导入时间库time.
import time getTime = time.strftime('%Y-%m-%d %H:%M:%S') print(getTime)
结果如下
D:\tools\Python37-32\python.exe E:/samples/modules/m0.py
2019-07-29 14:59:49
如果我们要调用外部的计算机程序,只需要导入os操作库os
#调用外部的计算机程序,以QQ为例子 import os os.system(r'D:\Tencent\QQ\Bin\QQScLauncher.exe')
就可以打开计算机程序了。
内置库非常丰富,大家可以在需要的时候,用搜索引擎搜索一下就可以找到范例代码了
10.5.模块搜索路径
上面学习中,你可能会有个疑问。我们用import或者from ... import来导入模块的时候python解释器是怎么找到模块文件
并且加载出来的
python是根据sys模块的一个变量内容sys.path的列表值来决定的,我们看一个例子:
那么sys.path的值又是怎么来的呢?
python解释器启动过程中一般会将下面的路径加到sys.path里面去
** 启动脚本所在的目录
** PYTHPATH环境变量里包含的目录,如果没有设置则忽略。该环境变量设置和PATH环境变量的设置方法类似
** 标准库目录,已经随着python的安装进入到计算机的那个,就是那个 lib/site-pacjages目录
** lib/site-packages下面.pth文件里指定的路径
上面列出的路径是python解释器启动过程自动得到的搜索路径,当然我们也可以自行修改那个sys.path里面的内容
,动态的改变模块搜索路径。课堂上我们会给出一个实际的例子