六、模块
一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀
为何要使用模块:
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变来那个都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当作脚本去执行,还可以把他们当作模块来导入到其他的模块中,实现了功能的重复利用
常用模块
collections模块
在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。
1)namedtuple:生成可以使用名字来访问元素内容的tuple
我们知道tuple可以表示不变集合,例如,一个点的二维坐标可以表示成:
p = (1,2)
但是,看到(1,2)很难看出这个tuple是用来表示一个坐标
这时,namedtuple就派上了用场
#namedtuple('名称',[属性list]) from collections import namedtuple point = namedtuple('point',['x','y']) p = point(1,2) p.x p.y
类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple定义:
circle = namedtuple('circle',['x','y','r'])
2)deque:双端队列,可以快速的从另外一侧追加和推出对象
使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低
deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈
from collections import deque q = deque(['a','b','c']) q.append('x') q.appendleft('y') q
deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素
3)OrderedDict:有序字典
使用dict时,key是无序的,在对dict做迭代时,我们无法确定key的顺序
如果要保持key的顺序,可以用OrderedDict:
from collections import OrderedDict d = dict([('a',1),('b',2),('c',3)]) d #dict的key是无序的 od = OrderedDict([('a',1),('d',2),('c',3)]) od #OrderedDict的key是有序的
OrderedDict([('a', 1), ('d', 2), ('c', 3)]) #注意,OrderedDict的key会按照插入的顺序排列,不是key本身排序
4)defaultdict:带有默认值的字典
有如下值集合[11,22,33,44,55,66,77,88,99,90...],将所有大于66的值保存至字典的第一个key中,将小于66的值保存至第二个key的值中
即: {
'k1'
: 大于
66
,
'k2'
: 小于
66
}
1.使用模块
python本身就内置了很多非常有用的模块,只要安装完毕,这些模块就可以立刻使用
我们以内建的sys模块为例,编写一个hello的模块
import sys
def test():
args = sys.argv
if len(args)==1:
print('Hello,world!')
elif len(args)==2: print('Heool,%s!'%args[1]) else: print('Too many arguments') if __name__=='__main__': test()
导入sys模块后,我们就有了变量sys指向该模块,利用sys这个变量,就可以访问sys模块所有功能
sys模块有一个argv变量,用list存储了命令行的所有参数。argv至少有一个元素,因为第一个参数永远是该.py文件的名称,例如:
运行python3 hello.py获得的sys.argv就是['hello.py']
运行python3 hello.py Michael获得的sys》argv就是['hello.py','Michael']
最后,注意到这两行代码
if __name__ == '__main__':
test()
当我们在命令行运行hello模块文件时,python解释器把一个特殊变量__name__置为__main__,而如果在其他地方导入该hello模块时,if判断将失败
因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试
作用域
在一个模块中,我们可能会定义很多的函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用,在python中,是通过_前缀来实现的
正常的函数和变量名是公开的(public),可以被直接引用,比如:abc,x123,pi等
类似__xx__这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__,__name__就是特殊变量
hello模块定义的文档注释也可以用特殊变量__doc__访问,我们自己的变量一般不要用这种变量名
类似于_xxx和__xxx这样的函数或变量就是非公开的(private)。不应该被直接引用,比如_abc,__abc等
之前我们说,private函数和变量不应该被直接引用,而不是不能被直接引用,是因为python并没有一种方法可以完美限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量
private函数或变量不应该被别人引用,那他们有什么用吗?请看例子:
def _private_1(name):
return 'Hello, %s' %name
def _private_2(name):
return 'Hi, %s'%name
def greeting(name):
if len(name)>3: return _private_1(name) else: return _private_2(name)
我们在模块里公开greeting()函数,而把内部逻辑用private函数隐藏起来了,这样,调用greeting()函数不用关心内部的private函数细节,这也是一种非常有用的代码封装和抽象的方法,即:
外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public
2.安装第三方模块
python模块,是一个python文件,以.py结尾,一个.py文件就称之为一个模块(Module),包含了python对象定义和python语句
模块让你能够有逻辑地组织你的python代码段
把相关的代码分配到一个模块里能让你的代码更好用,更易懂
模块能定义函数,类和变量,模块里也能包含可执行的代码
举个例子,一个abc.py的文件就是一个名字叫abc的模块,一个xyz.py的文件就是一个名字叫xyz的模块,假设我们的abc和xyz这两个模块名字与其他模块冲突了,于是我们可以通过包来组织模块。若放在了mycompany,此时abc.py模块的名字就变成了mycompany.abc,类似的,xyz.py的模块名变成了mycompany.xyz
import 语句
模块的引入
模块定义好后,我们可以使用import语句来引入模块,语法如下:
import module1[,module2[,...moduleN]]
比如要引用模块math,就可以在文件最开始的地方用import math来引入,在调用math模块中的函数时,必须这样引用:模块名.函数名
当解释器遇到import语句,如果模块在当前的搜索路径就会被导入
搜索路径是一个解释器会先进行搜索的所有目录的列表,如想要导入模块support.py,需要把命令放在脚本的顶端
导入模块:
import support
现在可以调用模块里包含的函数了
support.print_func('Runoob')
一个模块只会被导入一次,不管你之行了多少次import,这样可以防止导入模块被一遍又一遍地执行
from...import语句
python的from语句让你从模块中导入一个指定的部分到当前命名空间中,语法如下:
from modname import name1[,name2[,...nameN]]
例如要导入模块fib的fibonacci函数,使用如下语句:
from fib import fibnacci
这个声明不会把整个fib模块导入到当前的命名空间中,他只会将fib里的fibonacci单个引入到执行这个声明的模块的全局符号表
from...import* 语句
把一个模块的所有内容全都导入到当前的命名空间也是可行的,只是需要使用如下声明:
from modname import *
这提供了一个简单的方法来导入一个模块中的所有项目,然而这种声明不该被过多的使用
例如我们想一次性引入math模块中所有的东西,语法如下:from math import *
搜索路径
当你导入一个模块,python解析器对模块位置的搜索顺序是:
1.当前目录
2.如果不在当前目录,python则搜索在shell变量PYTHONPATH下的每个目录
3.如果都找不到,python会查看默认路径,UNIX下,默认路径一般为/usr/local/lib/python/
模块搜索路径存储在system模块的sys.path变量中,变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录
PYTHONPATH变量
作为环境变量,PYTHONPATH由装在一个列表里的许多目录组成,PYTHONPATH的语法和shell变量PATH一样
在python中,安装第三方模块,是通过包管理工具pip完成的
如果你正在使用Mac或linux,安装pip本身这个步骤就可以跳过;#如果你正在使用windows,请参考安装python一节的内容,确保安装勾选了pip和Add python.exe to path
在命令提示符窗口下尝试运行pip,如果windowd提示未找到命令,可以重新运行安装程序调价pip
pip install Pillow