第五章 模块与函数
5.1 python程序的结构
函数+类->模块 模块+模块->包 函数+类+模块+包=Python
python的程序由包(package)、模块(module)和函数组成。模块是处理某一类问题的集合,模块由函数和类组成。包是由一系列模块组成的集合。如图所示:
包就是一个完成特定任务的工具箱,python提供了许多有用的工具包,如字符串处理、图形用户接口、Web应用、图形图像处理等。使用自带的这些工具包,可以提高程序员的开发效率,减少编程的复杂度,达到代码重用的效果。这些自带的工具包和模块安装在Python的安装目录下的lib子目录中。
例如,lib目录中的xml文件夹。xml文件夹就是一个包,这个包用于完成XML的应用开发。xml包中有几个子包:dom、sax、etree和parsers。文件__init__.py是xml包的注册文件,如果没有该文件,Python将不能识别xml包。在系统字典表中定义了xml包。
注意:包必须至少含有一个__init__.py文件。__init__.py文件的内容可以为空,它用于识别当前文件夹是一个包。
5.2 模块
模块是python中重要的概念,python的程序是由一个个模块组成的。前面已经接触到了模块,一个python文件就是一个模块。
5.2.1 模块的创建
模块由代码、函数或类组成。创建一个名为myModule.py的文件,即定义了一个名为myModule的模块。在myModule模块中定义一个函数func()和一个类MyClass 。MyClass类中定义一个方法myFun()。
#!/usr/bin/env python
#vim myModule.py
#自定义模块
def func(): #函数
print("MyModule.func()")
class MyClass: #类
def myFunc(self):
print("MyModule.MyClass.myFunc()")
#!/usr/bin/env python
#vim call_myModule.py
#调用自定义模块的类和函数
import myModule
myModule.func()
myClass=myModule.MyClass()
myClass.myFunc()
[root@Dannyserver danny]# python call_myModule.py
MyModule.func()
MyModule.MyClass.myFunc()
注意:模块myModule.py和call_myModule.py需要在同一目录下,或放在sys.path所列出的目录下;否则python解释器找不到自定义的模块
当python导入一个模块时,python首先查找当前路径,然后查找lib目录、site-packages目录(Python\Lib\site-packages)和环境变量PYTHONPATH(pythonpath)设置的目录。如果导入的模块没有找到,在以上路径搜索下是否含有这个模块。可以通过sys.path语句搜索模块的查找路径。
5.2.2 模块的导入
模块的导入使用import语句,如:
import module_name
以模块名作为前缀,其格式如下:
module_name.func()
前缀符,可以使用from...import...语句导入。格式如下:
from module_name import function_name
后面调用function_name就等同于调用module_name.function_name
导入模块下所有的类和函数,可以使用如下格式:
from module_name import *
此外,同一个模块文件支持多条import语句。例如,定义一个名为myModule的模块。该模块定义一个全局变量count和一个函数func()。每次调用函数func(),使变量count的值加1。
#vim myModule.py
count=1
def func():
global count
count=count+1
return count
#vim a.py
import myModule
print("count=", myModule.func())
myModule.count=10
print("count=",myModule.count)
import myModule
print("count=",myModule.func())
[root@Dannyserver test2]# python a.py
count= 2
count= 10
count= 11
python中的import语句比Java的import语句更加灵活。python的import语句可以置于程序中任意的位置,甚至可以放在条件语句中,在上面的代码段添加如下语句:
if myModule.count>1:
myModule.count=1
else:
import myModule
print("count=", myModule.count)
输出结果
[root@Dannyserver test2]# python a.py
count= 2
count= 10
count= 11
count= 1
5.2.3 模块的属性
模块有一些内置属性,用于完成特定的任务,如__name__、__doc__。每个模块都有一个名称,例如,__name__用于判断当前模块是否是程序的入口,如果当前程序正在被使用,__name__的值为“__main__”。通常给每个模块都添加一个条件语句,用于单独测试该模块的功能。例如,创建一个模块myModule。
if __name__=="__main__":
print("myModule作为主程序运行")
else:
print("myModule被另一个模块调用")
单独运行该模块输出结果:
[root@Dannyserver test2]# python a.py
myModule作为主程序运行
创建另一个模块call_myModule。这么模块很简单,只要导入模块myModule即可
import myModule
print(__doc__) #调用了模块另一个属性__doc__。由于该模块没有定义文档字符串,所以输出None
[root@Dannyserver test2]# python call_myModule.py
myModule被另一个模块调用
None
5.2.4 模块的内置函数
Python提供了一个内联模块buildin。内联模块定义了一些开发中经常使用的函数,利用这些函数可以实现数据类型的转换、数据的计算、序列的处理等功能。下面将介绍内联模块中常用的函数。
1. apply()
python3中移除了apply函数,所以不再可用了。调用可变参数列表的函数的功能只能使用在列表前添加*来实现。
2. filter()
filter()可以对某个序列做过滤处理。判断自定义函数的参数返回的结果是否为真来过滤,并一次性返回处理结果。filter()的声明如下所示
class filter(object)
filter(function or None,iterable) -->filter object
filter()过滤序列的功能示例:
def func(x):
if (x>0):
return x
print (filter(func,range(-9,10))) #调用filter函数,返回的是filter对象
print(list(filter(func,range(-9,10)))) #将filter对象转换为列表
[root@Dannyserver test2]# python a.py
<filter object at 0x7fd4f762a160> #直接打印出的是filter对象,无法看到内容
[1, 2, 3, 4, 5, 6, 7, 8, 9] #将filter对象转换为列表
说明:第三行代码,使用range()生成待处理的列表,然后把该列表的值依次传入func()。func返回结果给filter(),最后将结果生成一个可迭代对象返回,可以进行遍历。
注意:filter()中的过滤函数func()的参数不能为空。否则,没有可以存储序列(sequence)元素的变量,func()也不能处理过滤。
3.reduce()
对序列中元素的连续操作可以通过循环来处理。例如,对某个序列中的元素累加操作。Python提供的reduce()也可以实现连续处理的功能。在python2中reduce()存在与全局空间中,可以直接调用。而在python3中将其移到了functools模块中,所以使用之前需要先引入。reduce()的声明如下所示:
reduce(func,sequence[ , initial]) ->value
说明:
参数func是自定义的函数,在函数func()中实现对参数sequence的连续操作。
参数sequence是待处理的序列
参数inital可以省略,如果inital不为空,则inital的值将首先传入func()进行计算。如果sequence为空,则对initial的值进行处理。
reduce()的返回值是func()计算后的结果。
下面实现了对一个列表的数字进行累加的操作。
def sum(x,y):
return (x+y)
from functools import reduce #引入reduce
print(reduce(sum,range(0,10))) #0+1+2+3+4+5+6+7+8+9
print(reduce(sum,range(0,10),10)) #10+0+1+2+3+4+5+6+7+8+9
print(reduce(sum,range(0,0),10)) #range(0,0)返回0,所以直接返回后面的10
[root@Dannyserver test2]# python a.py
45
55
10
注:reduce()还可以对数字进行乘法、阶乘等复杂的累计计算。如果用reduce()进行累计计算,必须在sum中定义两个参数,分别对应加法运算符两侧的操作表。
4.map()
map()可以对tuple元组进行“解包”操作,调用时设置map()的第一个参数为None。map()的功能非常强大,可以对多个序列的每个元素都执行相同的操作,并返回一个map对象。map()的声明如下所示:
class map(object)
map(func,*iterables) -->map object
说明:
参数func()是自定义的函数,实现对序列每个元素的操作
参数iterables是待处理的序列,参数iterables的个数可以是多个
map()的返回值是对序列元素处理后的列表。
下面这段代码实现了列表中数字的幂运算
def power(x):
return (x**x)
print(map(power,range(1,5))) #打印map对象
print(list(map(power,range(1,5)))) #转换为列表输出
def power2(x,y):
return (x**y)
print(map(power2,range(1,5),range(5,1,-1))) #打印map对象
print(list(map(power2,range(1,5),range(5,1,-1)))) #转换为列表输出,提供两个列表参数。依次计算1^5、2^4、3^3、4^2
[root@Dannyserver test2]# python a.py
<map object at 0x7f3d35d97208>
[1, 4, 27, 256]
<map object at 0x7f3d35d97240>
[1, 16, 27, 16]
注意:如果map()中提供多个序列,则每个序列中的元素一一对应进行计算,如上。如果每个序列的长度不同,则短的序列后补充None再进行计算。