模块
1、模块就是程序
任何python程序都可以作为模块导入:
>>>import sys
>>>sys.path.append('C:/python')
注:在unix中不能直接将字符串"~/python"附加到sys.path末尾。而必须使用绝对路径。如果要自动创建完整路径,可使用sys.path.expanduser('~/python')
当导入模块后,在其所在目录还新建了一个名为_pycache_的子目录,这个目录包含处理后的文件
模块导入一次和多次是一样的,若要重新加载模块,可使用模块importlib中的函数reload:
>>>import importlib
>>>python = importlib.reload(python)
2、模块是用来定义的
1> 在模块中定义函数:
只包含一个简单函数的模块:
# hello2.py
def hello():
print("hello,world")
导入改模块:
>>>import hello2
访问这个函数:
>>>hello2.hello()
---> hello,world
在模块的全局作用域内定义的名称都可以像这样访问。主要是为了重用代码,将代码放在模块中,就可以在多个程序中使用。
2> 在模块中添加测试代码
该模块中,测试代码不完善:
# hello3.py
def hello():
print("hello,world")
#一个测试
hello()
>>>import hello3
---> hello,world
>>>hello3.hello()
---> hello,world
检查模块是作为程序运行还是被导入另一个程序,为此需要使用变量__name__
>>>hello3.__name__
---> hello3
在主程序中,变量__name__的值是__main__,而在导入的模块中,这个变量被设置为该模块的名称
一个包含有条件的执行的测试代码的模块:
# hello4.py
def hello():
print("hello,world")
def test():
hello()
if __name__ =='__main__': test()
如果这个模块作为程序运行,将执行函数hello;如果导入,其行为像普通模块一样。
>>>import hello4
>>>hell4.hello()
---> hello,world
>>>hell4.test()
---> hello,world
3> 让模块可用:将模块放在正确的位置,告诉解释器到哪里去找
将模块放在正确的位置:
>>> import sys,pprint
>>> pprint.pprint(sys.path)
['',
'C:\soft\python\python3\py3install\Lib\idlelib',
'C:\soft\python\python3\py3install\python36.zip',
'C:\soft\python\python3\py3install\DLLs',
'C:\soft\python\python3\py3install\lib',
'C:\soft\python\python3\py3install',
'C:\soft\python\python3\py3install\lib\site-packages']
可将其放在其中的任何一个位置中都可行,但目录site-packages是最佳的选择,专门用来放置模块的
告诉解释器到哪里去找:
可以直接修改sys.path(不常见)
标准做法:将模块所在的目录包含在环境变量PYTHONPATH中:
如:将~/python附加到环境变量PYTHONPATH末尾中:export PYTHONPATH=$PYTHONPATH:~/python
3、模块包含什么
使用函数dir:
查看模块包含哪些东西,可使用函数dir,它列出对象的所有的属性(对于模块,列出所有的函数,类,变量)
>>>dir(copy)
['Error', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_copy_dispatch', '_copy_immutable', '_deepcopy_atomic', '_deepcopy_dict', '_deepcopy_dispatch', '_deepcopy_list', '_deepcopy_method', '_deepcopy_tuple', '_keep_alive', '_reconstruct', 'copy', 'deepcopy', 'dispatch_table', 'error']
注:以下划线开头的名称列表,并非供外部使用。
>>> [n for n in dir(copy) if not n.startswith('_')]
['Error', 'copy', 'deepcopy', 'dispatch_table', 'error']
变量__all__
如:
>>> copy.__all__
['Error', 'copy', 'deepcopy']
查看文档:
>>>print(copy.__doc__)
Generic (shallow and deep) copying operations.
Interface summary:
import copy
x = copy.copy(y) # make a shallow copy of y
x = copy.deepcopy(y) # make a deep copy of y
使用源代码,查看某特性
>>>print(copy.__file__)
C:softpythonpython3py3installlibcopy.py
标准库(标准模块)
1、sys
模块sys中一些重要的函数和变量
argv :命令行参数,包括脚本名
exit([arg]) :退出当前程序,可通过可选参数指定返回值或错误消息
modules:一个字典,将模块名映射到加载的模块
path:一个列表,包含要在其中查找模块的目录的名称
platform:一个平台标识符,如win32或rhel6
stdin:标准输入流,一个类似于文件的对象
stdout:标准输出流,一个类似于文件的对象
stderr:标准错误流,一个类似于文件的对象
变量sys.argv:包含传递给python解释器的参数,其中包括脚本名
函数sys.exit:退出当前程序。可以向它提供一个整数,指出程序是否成功,这是一种unix约定,大多数情况下,使用该参数的默认值(0,表示成功)即可。也可向它提供一个字符串,这个字符串将成为错误消息,程序退出时将显示指定的错误消息以及一个表示失败的编码。
映射sys.modules:将模块名映射到模块(仅限当前已导入的模块)
变量sys.path:它是一个字符串列表,其中的每个字符串都是一个目录名,执行import语句时将在这些目录中查找模块。
变量sys.platform:是运行解释器的“平台”名称,
2、os
environ:包含环境变量的映射
system(command):在子shell中执行操作系统命令
sep:路径中使用的分隔符
pathsep:分割不同路径的分隔符
linesep:行分隔符(
,
,
)
urandom(n):返回n个字节的强加密随机数据
os.environ:包含环境变量,如要访问的环境变量PYTHONPATH,可使用表达式os.environ[PATHONPATH];也可用于修改环境变量。
os.system:用于运行外部程序。还有其它用于执行外部程序的函数,如execv或popen。前者退出python解释器,并将控制权交给被执行的程序,而后者创建一个到程序的连接。
变量os.sep:是用于路径名中的分隔符。在unix中标准的分隔符为(/);在windows中标准分隔符为(\)
os.pathsep:可用来组合多条路径。pathsep用于分割不同的路径名,在unix中为(:),在windows中为(;)
变量os.linesep:用于文本文件中的行分隔符:在unix中为单个换行符(
),在windows中为回车和换行符(
)
函数urandom:使用随系统而异的随机源
启动浏览器:
在Unix中:os.system('/usr/bin/firefox');
在windows中:os.system(r'C:"Promgram Files (x86)""Mozilla Firefox"firefox.exe);(路径中有空白,需用引号将其括起来)
另可使用函数os.startfile:os.startfile(r'C:Promgram Files (x86)Mozilla Firefoxfirefox.exe);(路径中有空白也无影响)
在windows中,使用os.system和os.startfile启动外部程序后,当前的python程序将继续运行;而在unix中,当前Python程序将等待命令os.system结束。
使用webbrowser模块:该模块中包含一个名为open的函数,可以启动浏览器并打开指定的URL:
>>>import webbrowser
>>>webbbrowser.open('http://www.python.org')
3、fileinput
模块fileinput能够迭代一系列文本文件中的所有行。
input([files[,inplace[,backup]]]:帮助迭代多个输入流中的行。
filename():返回当前文件的名称
lineno():返回(累计的)当前的行号
filelineno():返回在当前文件中的行号
isfirstline:检查当前行是否是文件中的第一行
isstdin():检查最后一行是否来自sys.stdin
nextfile():关闭当前文件并移动到下一个文件
close():关闭序列
fileinput.input:返回一个可在for循坏中进行迭代的对象。如果要覆盖默认行为(确定要迭代哪些文件),可以序列的方式向这个函数提供一个或多个文件名。还可以将参数inplace设置为True(inplace=True),这样讲就地进行处理。对于访问的每一行,都需打印出替代的内容,这些内容将被写回到当前输入文件中。就地处理时,可选参数backup用于给从原始文件创建的备份文件制定扩展名。
函数fileinput.filename:返回当前文件(即当前所处理的行所属文件)的文件名。
函数fileinput.lineno:返回当前的行号。这个值是累计的,因此处理完一个文件并接着处理下个文件时,不会重置行号。
函数fileinput.filelineno:返回当前行在当前文件中的行号,每处理完一个文件并接着处理下个文件时,将重置这个行号并从1重新开始。
函数fileinput.isfirstline:在当前行是当前文件中的第一行时返回True,否则返回False。
函数fileinput.isstdin:在当前文件是sys.stdin时返回True,否则返回False。
函数fileinput.nextfile:关闭当前文件并跳到下一个文件,且计数时忽略跳过的行。
函数fileinput.close:关闭整个文件链并结束迭代。
eg:给文件中的每一行添加行号,每行代码最多包含40个字符,并在第41个字符处开始添加注释。
#numberlines.py
inport fileinput
for line in fileinput.input(inplace=True):
line = line.rstrip()
num = fileinput.lineno()
print('{:<50} # {:2d}'.format(line,num))
结果:
#numberlines.py #1
inport fileinput #2
for line in fileinput.input(inplace=True): #3
line = line.rstrip() #4
num = fileinput.lineno() #5
print('{:<50} # {:2d}'.format(line,num)) #6
4、集合、堆、双端队列
集合:是由内置的类Set实现的,所以可以直接创建集合,无需导入模块Sets
>>>set(range(10))
---> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
可以使用序列(或其它可迭代对象)来创建集合,也可使用花括号{}显式的指定(不能仅使用花括号{}来创建空集合,因为这样将创建一个空字典)
>>>type({}) ---><class 'dict'>
必须在不提供任何参数的情况下调用set。集合主要用于成员资格检查,因此将忽略重复的元素;集合中的元素排列顺序是不固定的;
>>> {0,1,2,3,4,5,0,1,2,3,6,7,8,9}
---> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
集合操作:交集,并集,位操作
堆:一种数据结构,是一种优先队列。优先队列能够以任意的顺序添加对象,并随时找出(并删除)最小的元素。
模块heapq:包含一些堆操作函数的模块。必须使用列表来表示堆对象本身:
heappush(heap,x):将x压入堆中
heappop(heap):从堆中弹出最小的元素
heapify(heap):让列表具备堆特征
heapreplace(heap,x):弹出最小的元素,并将x压入堆中
nlargest(n,iter):返回iter中n个最大的元素
nsmallest(n,iter):返回iter中n个最小的元素
函数heappush用于在堆中添加一个元素。不能将其用于普通列表,而只能用于使用各种堆函数创建的列表(原因是元素的顺序很重要)。
>>>from heapq import *
>>>from random import shuffle
>>>data = list(rang(10))
>>>data ---> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>shuffle(data)
>>>data ---> [2, 1, 5, 7, 6, 8, 9, 3, 4, 0]
>>>heap = []
>>>for n in data
heappush(heap,n)
>>>heap
--->[0, 1, 5, 3, 2, 8, 9, 7, 4, 6]
>>> heappush(heap,0.5)
>>> heap
[0, 0.5, 5, 3, 1, 8, 9, 7, 4, 6, 2]
堆特征:位置i处的元素总是大于位置i//2处的元素(反过来:小于位置2*i和2*i+1处的元素)
函数heappop:弹出最小的元素(总是位于索引0处),并确保剩余元素中最小的那个元素位于索引0处,
>>> heap ---> [0, 0.5, 5, 3, 1, 8, 9, 7, 4, 6, 2]
>>> heappop(heap)
0
>>> heap ---> [0.5, 1, 5, 3, 2, 8, 9, 7, 4, 6]
函数heapify通过执行尽可能少的移位操作将列表变成合法的堆(即具备堆特征):若堆不是使用heappush创建的,应在使用heappush和heappop之前使用这个函数:
>>> heap = [5,1,6,7,2,3,8,4,0,9]
>>>heapify(heap)
>>> heap --->[0, 1, 3, 4, 2, 6, 8, 5, 7, 9]
函数heapreplace:从堆中弹出最小的元素,再压入一个新元素
>>> heap = [5,1,6,7,2,3,8,4,0,9]
>>> heapreplace(heap,1.5)
0
>>> heap ---> [1, 1.5, 3, 4, 2, 6, 8, 5, 7, 9]
双端队列(及其它集合)
双端队列也是从可迭代对象创建的;可用于在需要按添加元素的顺序进行删除。在模块collections中,包含类型deque以及其它几个集合类型
>>>from collections import deque
>>> q = deque(range(5))
>>> q ---> deque([0, 1, 2, 3, 4])
>>> q.append(5)
>>> q ---> deque([0, 1, 2, 3, 4, 5])
>>> q.appendleft(6)
>>> q ---> deque([6, 0, 1, 2, 3, 4, 5])
>>> q.pop()
5
>>> q ---> deque([6, 0, 1, 2, 3, 4])
>>> q.popleft()
6
>>> q ---> deque([0, 1, 2, 3, 4])
>>> q.rotate(3)
>>> q ---> deque([2, 3, 4, 0, 1])
>>> q.rotate(-1)
>>> q ---> deque([3, 4, 0, 1, 2])
注:rotate移动元素的位置
双端队列支持在队首(左端)高效的附加和弹出元素,而列表无法这样做;另还可以高效的旋转元素(将元素向左或向右移动,并在到达一端时环绕到另一端)
5、time
模块time:包含用于获取当前时间,操作时间和日期,从字符串中读取日期,将日期格式化为字符串的函数。
日期可以表示为实数(从新纪元1月1日0时起过去的秒数,unix中新纪元为1970年),也可表示为包含9个整数的元组。
元组:(2008,1,21,12,2,56,0,21,0)表示2008年1月21日12时2分56秒,这一天是星期一,2008年的第21天(不考虑夏令时)
元组中的字段:
0:年
1:月
2:日
3:时
4:分
5:秒 (范围0~61,考虑了闰一秒和闰两秒的情况)
6:星期* (范围0~6:0表示星期一)
7:儒略日(范围1~366)
8:夏令时(0、1或-1)布尔值(True或False)
asctime([tuple]):将时间元组转换为字符串
localtime([secs[):将秒数转换为表示当地时间的日期元组
mktime([tuple]):将时间元组转换为当地时间
sleep([secs]):休眠secs秒
striptime(string[,format]):将字符串转换为时间元组
time():当前时间(从新纪元时间开始后的秒数,以UTC为准)
函数time.asctime:将当前时间转换为字符串
>>> import time
>>> time.asctime() ---> 'Sun Jun 3 10:48:55 2018'
若不想使用当前时间,也可向其提供一个日期元组(如localtime创建的日期元组),要设置更复杂的格式,可使用函数strftime>
函数time.localtime:将一个实数(从新纪元开始后的秒数)转换为日期元组(本地时间),若要转换为国际标准时间,应使用gmtime。
函数time.mktime:将日期元组转换为从新纪元后的秒数,与localtime的功能相反
函数time.sleep:让解释器等待指定的秒数。
函数time.strptime:将一个字符串(其格式与asctime所返回字符串的格式相同)转换为日期元组。
函数time.time:返回当前的国际标准时间,以从新纪元开始的秒数表示
另模块datatime:提供了日期和时间算术支持,模块timeit:可帮助计算代码段的执行时间
6、random
模块random:包含生成伪随机数的函数。另真正的随机:模块os中的函数urandom
random():返回一个0~1的随机实数
getrandbits(n):以长整数方式返回n个随机的二进制位
uniform(a,b):返回一个a~b(含)的随机实数
randrange([start],stop,[step]):从range(start,stop,step)中随机的选择一个数
choice(seq):从序列seq中随机的选择一个元素
shuffle(seq[,random]):就地打乱序列seq
sample(seq,n):从序列seq中随机的选择n个值不同的元素
7、shelve、json
shelve:数据存储;模块shelve中的函数open,将一个文件名作为参数,并返回一个shelf对象,用来存储
>>> s = shelve.open('test.txt')
>>> s['x'] = ['a','b','c']
>>> s['x'].append('d')
>>> s['x'] ---> ['a', 'b', 'c']
注:当查看shelf对象中的元素时,将使用存储版重建该对象,而当将一个元素赋值给键时,该元素被存储
要准确的修改使用模块shelve储存的对象,必须将获取的副本赋给一个临时变量,并在修改这个副本后再次存储:
>>> temp = s['x']
>>> temp ---> ['a', 'b', 'c']
>>> temp.append('f')
>>> temp ---> ['a', 'b', 'c', 'f']
>>> s['x'] ---> ['a', 'b', 'c']
>>> s['x'] = temp
>>> s['x'] ---> ['a', 'b', 'c', 'f']
8、re
模块re:提供对正则表达式的支持
(1)正则表达式:
-通配符:句点(.)只与一个字符匹配,而不与0个或两个字符匹配(换行符除外)
-对特殊字符进行转义:反斜杠()
-字符集:[a-z]:a~z的任何字母;[a-zA-Z0-9]:大小写字母和数字。字符集只能匹配一个字符;
要指定排除字符集:在开头添加^字符;
-二选一和子模式:管道字符(|),'python|perl';子模式:'p(ython|erl)'
-可选模式和重复模式:通过在子模式后面加上问号,将其指定为可选的,即可包含可不包含
eg:r'(http://)?(www.)?python.org'
注:对句点进行了转义;每个可选的子模式都可以出现,也可以不出现;
(pattern)*:pattern可重复0、1或多次
(pattern)+:pattern可重复1或多次
(pattern){m,n}:pattern可重复m~n次
字符串的开头和末尾:在字符串的开头或末尾查找匹配的字符串:使用脱字符^指定开头,使用$指定字符串的末尾
(2)模块re中包含多个正则表达式的函数:
compile(pattern[,flags]):根据包含正则表达式的字符串创建模式对象
search(pattern,string[,flags]):在字符串中查找模式
match(pattern,string[,flags]):在字符串开头匹配模式
split(pattern,string[,maxsplit=0]):根据模式来分割字符串
findall(pattern,string):返回一个列表,其中包含字符串中所有与模式匹配的子串
sub(pat,repl,string[,count=0]):将字符串中与模式pat匹配的子串都替换为repl
escape(string):对字符串中所有的正则表达式特殊字符都进行转义
注:flags为可选参数,用于修改正则表达式的解读方式
函数re.compile:将用字符串表示的正则表达式转换为模式对象,调用search,match等函数时,如果提供的事用字符串表示的正则表达式,都必须在内部将它们转换为模式对象
函数re.search:在给定的字符串中查找第一个与指定正则表达式匹配的子串。如果找到这样的子串,将返回MatchObject(结果为真),否则返回None(结果为假)
函数re.match:在给定字符串开头查找与正则表达式匹配的子串;函数match在模式与字符串开头匹配时就返回True,而不是要求模式与整个字符串匹配;若要与整个字符串都匹配,需要在模式末尾加上一个$符号
函数re.split:根据与模式匹配的子串来分割字符串,类似于字符串方法split;如使用空格和逗号(,)作为分隔符来分割字符串:re.split('[, ]+',some_content)
注:如果模式包含括号(),将在分割得到的子串之间插入括号中的内容,eg:re.split('o(o)','foobar'),其结果为:['f', 'o', 'bar']
参数maxsplit:指定最多分割的次数
函数re.findall:返回一个列表,其中包含所有与给定模式匹配的子串
eg:找出字符串中包含的所有单词:
>>>pat='[a-zA-Z]+'
>>>text='"HM.... ERR......are you sure?" he said,sounding insecure.'
>>>re.findall(pat,text)
---> ['HM', 'ERR', 'are', 'you', 'sure', 'he', 'said', 'sounding', 'insecure']
查找所有的标点符号:
>>>pat = r'[.?-",]+' --对符号(-)进行了转义
>>>re.findall(pat,text)
---> ['"', '....', '......', '?"', ',', '.']
函数re.sub:从左往右将与模式匹配的子串替换为指定内容
eg:>>>pat = '{name}'
>>>text = 'hello {name}......'
>>>re.sub(pat,'Alex',text)
---> 'hello Alex......'
re.escape:是一个工具函数。用于对字符串中所有可能被视为正则表达式运算符的字符进行转义。使用这个函数的情况:字符串很长,其中包含大量的特殊字符,而不想输入大量的反斜杠转义
(3)匹配对象和编组
在模块re中,查找与模式匹配的子串的函数都在找到是返回MatchObject对象。这个对象包含与模式匹配的子串信息,还包含模式的哪部分与子串的哪部分匹配的信息。这些子串称为编组。
编组就是放在圆括号内的子模式,是根据左边的括号数编号的,其中编组0指的是整个模式。
re匹配对象的重要方法:
group([group1,...]):获取与给定子模式(编组)匹配的子串
start([group]):返回与给定编组匹配的子串的起始位置
end([group]):返回与给定编组匹配的子串的终止位置(与切片一样,不包含终止位置)
span([group]):返回与给定编组匹配的子串的起始位置和终止位置
eg:
>>>m = re.match(r'www.(.*)..{3}','www.python.org')
>>>m.group(0) ---> 'www.python.org'
>>>m.group(1) ---> 'python'
>>>m.start(1) ---> 4
>>>m.end(1) ---> 10
>>>m.span(1) ---> (4, 10)
(4)替换中的组号和函数
在替代字符串中使用组号:在替换字符串中,任何类似于"\n"的转义序列都将被替换为与模式中编组n匹配的字符串。
如:将"*something*"替换为"<em>something</em>
创建正则表达式:
>>>emphasis_pattern=r'*([^*]+)*'
或者在调用模块re中的函数时使用标志VERBOSE,可以在模式中添加空白(空格,制表符,换行符)
>>>emphasis_pattern=re.compile(r'''*([^*]+)*''',re.VERBOSE)
>>>re.sub(emphasis_pattern,r'<em>1</em>','hello,*world*')
----> 'hello,<em>world</em>'
>>> emphasis_pattern=r'*(.+)*' ---以星号开头和结尾的内容匹配,匹配了从第一个星号到最后一个星号的全部内容
>>>re.sub(emphasis_pattern,r'<em>1</em>','*this* is *it*')
---> '<em>this* is *it</em>'
>>> emphasis_pattern=r'*(.+?)*'
>>>re.sub(emphasis_pattern,r'<em>1</em>','*this* is *it*') ---使用运算符+?,将匹配一个或多个通配符,但匹配尽可能少的内容
---> '<em>this</em> is <em>it</em>'