Python 第四篇:生成器、迭代器、装饰器、递归函数与正则表达式
一:生成器:Generator,可以理解为是一种一个函数产生一个迭代器,而迭代器里面的数据是可以通过for循环获取的,那么这个函数就是一个生成器,即生成器是有函数生成的,创建生成器使用()表示,比如g = (x for x in range(10)),那么即创建一个名称为g的生成器,,如果外层是[]则表示是生成一个列表,生成器生成的序列可以使用next()方法获取其中的值:
1.__next__()方法获取序列中的值:
g1 = (x for x in range(3))
print(type(g1),"print(type(g1)的结果")
print(g1,"print(g1)的结果")
print(g1.__next__())
print(g1.__next__())
print(g1.__next__()) 执行结果;
<class 'generator'> print(type(g1)的结果
<generator object <genexpr> at 0x101b817d8> print(g1)的结果
0
1
2 如果是[]表示,则在使用__next__()取值的时候保存,会提示没有__next__()方法: g1 = [x for x in range(3)]
print(g1.__next__()) 执行结果:
Traceback (most recent call last):
File "/Users/zhangshijie/PycharmProjects/S12-Python3/day4/11.py", line 5, in <module>
print(g1.__next__())
AttributeError: 'list' object has no attribute '__next__'
_next__()获取序列中的值
2.__next__()获取文件中的行:
def func():
with open("test.txt") as f:
try:
while True:
line = next(f) #每次读取一行,会自动换下一行
print(line,end='')
except StopIteration:
print("\n已经读取文件完成-->StopIteration执行")
func() 执行结果:
global
log 127.0.0.1 local2
daemon
maxconn 256
log 127.0.0.1 local2 info
defaults
log global
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option dontlognull listen stats :8888
stats enable
stats uri /admin
stats auth admin:1234
已经读取文件完成-->StopIteration执行
__next__()获取文件中的行
3.如果生成器生成的序列中的值已经全部被__netx__()方法取出,但是后续还要获取数据的话,则会抛出StopIteration异常,如下:
g1 = (x for x in range(3))
print(type(g1),"print(type(g1)的结果")
print(g1,"print(g1)的结果")
print(g1.__next__())
print(g1.__next__())
print(g1.__next__())
print(g1.__next__())
print(g1.__next__()) 执行结果:
<class 'generator'> print(type(g1)的结果
<generator object <genexpr> at 0x101b817d8> print(g1)的结果
0
1
2 #在执行完成这一条数据的获取之后就报异常了
Traceback (most recent call last):
File "/Users/zhangshijie/PycharmProjects/S12-Python3/day4/test.py", line 201, in <module>
print(g1.__next__())
StopIteration
StopIteration 异常
4.解决异常的办法:
g1 = (x for x in range(3))
for i in g1:
try:
print(type(g1),"print(type(g1)的结果")
print(g1,"print(g1)的结果")
print(g1.__next__(),"")
print(g1.__next__(),"")
print(g1.__next__(),"")
print(g1.__next__(),"")
print(g1.__next__(),"")
except StopIteration: #当捕获到指定的异常之后则执行以下的命令
print("数据已经或完成了")
执行结果:
<class 'generator'> print(type(g1)的结果
<generator object <genexpr> at 0x1012817d8> print(g1)的结果
1 1
2 2
数据已经或完成了
捕获StopIteration
二:迭代器,是一个可使用for循环遍历每一个元素的可迭代对象,之前学过的可迭代对象(Iterable)有以下几种,一是常见的数据类型,如列表list,元组tuple,字典dict,集合set,字串ztr等,二是生成器(generator)和yield的生成器方法(generator function),如果想知道一个对象是否是可迭代对象(Iterable),如:
1、使用isinstance()方法查看指定对象是否是可迭代对象,如:
from collections import Iterable
print(isinstance((10),Iterable),"10是否可迭代对象")
print(isinstance([],Iterable),"[]是否可迭代对象")
print(isinstance((),Iterable),"()是否可迭代对象")
print(isinstance({},Iterable),"{}是否可迭代对象")
print(isinstance("abcd",Iterable),"字符串abcd是否可迭代对象")
print(isinstance((x for x in range(10)),Iterable),"for生成的序列是否可迭代对象") 执行结果:
False 10是否可迭代对象
True []是否可迭代对象
True ()是否可迭代对象
True {}是否可迭代对象
True 字符串abcd是否可迭代对象
True for生成的序列是否可迭代对象
isinstance判断对象是否可迭代对象
2.使用isinstance()方法查看指定对象是否是迭代器,如:
from collections import Iterator
print(isinstance((10),Iterator),"10是否迭代器")
print(isinstance([],Iterator),"[]是否迭代器")
print(isinstance((),Iterator),"()是否迭代器")
print(isinstance({},Iterator),"{}是否迭代器")
print(isinstance("abcd",Iterator),"字符串abcd是否迭代器")
print(isinstance((x for x in range(10)),Iterator),"for生成的序列是否迭代器")
g1 = (x * x for x in range(10))
print(isinstance(g1,Iterator),"g1生成的序列是否迭代器") 执行结果:
False 10是否迭代器
False []是否迭代器
False ()是否迭代器
False {}是否迭代器
False 字符串abcd是否迭代器
True for生成的序列是否迭代器
True g1生成的序列是否迭代器
isinstance判断对象是否迭代器
3.迭代器(Iterator)和迭代对象(Iterable)的区别:
1、可以从其中通过for循环获取数据的都是可迭代对象(Iterable)
2、可以通过next()方法获取数据的对象都是迭代器(Iterator)
3、迭代器只是在通过使用next()方法获取数据的时候才会计算,因此比可迭代对象效率更高并在内存使用率更低,因为可迭代对象是一次生成。
4、迭代器执行过程中无法后退到上一个或返回到指定的元素,其只能通过next()方法继续往前执行
5、for循环的readlines方法是一次读取所有行并将所有行放在一个列表当中,read()方法是读取所有内容到内存并保存为字符串格式
三:递归函数:
函数的内部可以调用其他的函数,但是如果这个函数的内部在执行的时候调用了函数自身,那么这个函数就是递归函数,因此递归函数一定是在函数里实现的,即先声明一个函数然后在函数内部中调用自己,递归函数需要有一个明确的退出接口,因为如果不设置退出接口则会进入无限循环调用的场景,最终可能会导致内存用尽等场景:
1.创建一个简单的递归函数:
def func(num):
print(num)
if num > 1: #先判断num的值大于1才继续执行
func(num -1) #在函数的原基础之上执行数值减1
func(10) #传递的值为10 执行结果:
10
9
8
7
6
5
4
3
2
1
简单递归函数
2.使用递归函数计算斐波拉契(Fibonacci)算法
斐波拉契(Fibonacci)算法,即书第一个和第二个数值之外,这两个数值之后的任意一个数都是有前两位数值相加得出的,比如:0,1, 1, 2, 3, 5, 8, 13, 21, 34,55 ...这种结果如果用列表和for循环很不好计算,而且生成列表会生成很多用不到的数值,但是使用函数计算就比较简单了。
递归函数计算斐波那契算法的方法如下:
def func(num):
x = 0 #定义三个变量
y = 0
z = 1
while x < num: #假如x的值小于函数调用的时候传递的num的数值
print(z) #打印z的结果
y,z = z,y + z #将y的等于z的值,z的值等于y+z的值,即完成了后面的一个数的值是有前两个数值相加的结果
x += 1 #然后将x的值自增1
print("每次相加分割线--------->")
return z #将最终z的值返回给函数名,最后函数的值就等于z print(func(30)) 执行结果:
1
每次相加分割线--------->
1
每次相加分割线--------->
2
每次相加分割线--------->
3
每次相加分割线--------->
5
每次相加分割线--------->
8
每次相加分割线--------->
13
每次相加分割线--------->
21
每次相加分割线--------->
34
每次相加分割线--------->
55
每次相加分割线--------->
89
每次相加分割线--------->
144
每次相加分割线--------->
233
每次相加分割线--------->
377
每次相加分割线--------->
610
每次相加分割线--------->
987
每次相加分割线--------->
1597
每次相加分割线--------->
2584
每次相加分割线--------->
4181
每次相加分割线--------->
6765
每次相加分割线--------->
10946
每次相加分割线--------->
17711
每次相加分割线--------->
28657
每次相加分割线--------->
46368
每次相加分割线--------->
75025
每次相加分割线--------->
121393
每次相加分割线--------->
196418
每次相加分割线--------->
317811
每次相加分割线--------->
514229
每次相加分割线--------->
832040
每次相加分割线--------->
1346269
函数计算斐波那契算法
队规算法可用于解决以下问题:
- 数据的定义是按递归定义的,比如列表,Fibonacci函数)
- 问题解法可以安装按递归算法实现。(回溯)
- 数据的结构形式是按递归定义的。(比如树的遍历,图的搜索)
递归的缺点:递归算法解题的运行效率较低。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成内存栈溢出等。
函数返回值:
def func1(num):
return 3,6,9,num #多个值返回给函数名
print(func1(10))
a = list(func1(10))
print(a)
a,b,c,num = func1(11) #对函数返回值进行拆包,将返回值赋值给多个变量
print(a,"a从func1(11)执行结果获取到的值")
print(b,"b从func1(11)执行结果获取到的值")
print(c,"c从func1(11)执行结果获取到的值")
print(num,"num从func1(11)执行结果获取到的值") 执行结果:
(3, 6, 9, 10) #函数返回值默认是元组
[3, 6, 9, 10] #可以将元组转换为列表进行增删元素
3 a从func1(11)执行结果获取到的值
6 b从func1(11)执行结果获取到的值
9 c从func1(11)执行结果获取到的值
11 num从func1(11)执行结果获取到的值
函数返回值拆包
四:装饰器:
装饰器本身是一个函数,是为了不改变其他函数的代码和用户调用方法的情况下其他函数添加之前没有的功能,如下是一个简单的装饰器:
1.装饰器的函数是传递固定参数:
def login(func):
def inner(arg):
print("通过验证")
func(arg) #返回的是func形参的内存地址,这里func的实参是tc,因此返回了tc的内存地址
return inner @login
def tv(name):
print("欢迎%s登录tv界面" % name) tv = login(tv) #将tv作为函数login函数的执行参数传递过去
tv("jack")
2.装饰器的函数是传递动态参数:
def login(func): #此时的func等于tv的内存地址,而tv执行的时候需要两个参数*arg,**abc
def inner(*arg,**abc):
print("通过验证")
return func(*arg,**abc) #返回的是func形参的内存地址,这里func的实参是tc,因此返回了tc的内存地址
return inner #返回的是 @login
def tv(*arg,**abc):
print("欢迎登录tv界面") tv = login(tv) #将tv作为函数login函数的执行参数传递给login函数
tv("jack","pass=123") 执行结果:
通过验证
通过验证
欢迎登录tv界面 执行流程:
1.进入到第一行代码login(func)放入内存,不执行函数内部
2.到装饰器@login
3.返回到login,即第一行,因为对函数进行了调用,将login重新定义为tv = login(tv),即把被装饰的函数做为参数传递给装饰器并再赋值给函数本身
4.进入login内部,执行第一层函数inner,放入内存
5.inner的执行结果是inner得到内存地址,得到此地址是为了不做验证,不然装饰器一被调用就通过了验证
6.执行tv = login(tv),将函数tv作为参数传递给函数login,而login是个装饰器
7.返回到第一行login(func)
8.执行内部函数inner
9.将innter函数放在内存
10.执行tv("jack","pass=123")login(func),将实参传递给inner
11.进入到inner。此时的innter的arg是arg:("jack","pass=123") abc={} 12.return func(*arg,**abc)的结果给inner
13.退回到inner函数
14..return func(*arg,**abc),此时的值已经给了inner
15.执行装饰器@login
16.打印欢迎界面
3.给装饰器传递参数:
def Before(request,kargs): #第一步将函数放进内存
#第六步,在装饰器之后执行函数
#第十步执行装饰器的内部函数的参数,这次是一个外部函数
print('before') #十一部,print结果 def After(request,kargs): #第二部放进第二个内存
#十二部执行另一个函数
print('after') def Filter(before_func,after_func): #第三部按照顺序放进第三个函数
#第五步执行装饰器,并将装饰器的参数执行,本次为两个函数
def outer(main_func): #第六到装饰器里面的函数
#第八步从return返回到这个函数
def wrapper(request,kargs):
#第九步执行返回对应的函数,得到request,kargs的值
before_result = before_func(request,kargs)
if(before_result != None):
return before_result; main_result = main_func(request,kargs)
if(main_result != None):
return main_result; after_result = after_func(request,kargs)
if(after_result != None):
return after_result; return wrapper
return outer #第七部,装饰器里面的第一个函数返回这个函数内部的函数名,这个函数名是个未执行的内存地址
#第十部 @Filter(Before, After) #第四部到装饰器界面
def Index(request,kargs):
print('index') Index("aa","bb") 执行结果:
before
index
after
带参数的装饰器
五:python正则表达式基本方法:
正则表达式是处理字符串的一种工具,在很多语言里都支持,它是通过一定的规则语法,去指定的元素中匹配、查找和替换等操作字符串,在python里面是一个模块叫做re,通过import导入即可使用,re模块在python1.5版本添加,以下是是python 3.5.1当中的re模块常用方法:
1.compile(pattern, flags=0):将字符串转形式的正则表达式编译为Pattern对象,用于将常用的字符串转换成Pattern对象便于以后经常匹配这些字符串,然后返回RegexObject对象,最后可以通过RegexObject对象调用match()和search()方法,如:
import re
reb = re.compile(r'abc') #将要匹配的字符串提前编译好,利于以后调用
rec = reb.match("abcd") #在abcd中匹配编译好的abc
if rec:
print(rec)
print(rec.group(),"第一组匹配成功")
else:
print("第一组匹为匹配成功") rea = re.compile("abc")
red = rea.match("ab")
if red:
print(red.group(),"第二组匹配成功")
else:
print("第二组未匹配成功") 执行结果: <_sre.SRE_Match object; span=(0, 3), match='abc'> #为使用group的结果,因此要查看匹配到的字符串要使用group查看
abc 第一组匹配成功
第二组未匹配成功
compile
group():返回被正则表达式匹配成功的字符串
start():返回被正则表达式匹配成功字符串的开始下标位置
end():返回被正则表达式匹配成功的字符串结束的下标位置
snap():同时返回开始和结束位置
import re
s1 = re.search("","2nk11askd1") #search会从头到位匹配全部字符串当中是否有指定的字符串出现,在任意位置匹配成功都算成功
if s1:
print(s1.group(),"第一组匹配成功")
else:
print("s1匹配失败")
print() s2 = re.search("","11034a10bc") #在中间和结果匹配成功都算是匹配成功的
if s2:
print(s2.group(),"第一组匹配成功")
print(s2.start(),"start返回开始的索引")
print(s2.end(),"end返回结束的索引")
print(s2.span(),"span返回开始和结束的索引") else:
print("s2匹配失败")
2.escape(pattern):python3.4 新加,对字符串中的非字母数字进行转义,即对特殊字符和特殊符号做转义,在其前方加上反斜线\,如:
import re
print(re.escape("www.test.com,#mail,xxx@xx.com")) 执行结果:
www\.test\.com\,\#mail\,xxx\@xx\.com #在标点符号、特特殊字符前自动加上反斜线进行转义
3.findall(pattern, string, flags=0):以返回列表显示所有可以匹配到的结果,与search不同的是findall返回的是匹配到的所有结果,即返回的是不固定数量的结果,如:
import re
s1 = re.findall("","abc123abc123xy1234") #只匹配123
print(s1)
执行结果:
['', '', ''] import re
s1 = re.findall("12\d+","abc123abc123xy1234") #匹配12后面有一个或多个数值
print(s1)
执行结果:
['', '', '']
findall
4.finditer(pattern, string, flags=0):匹配所有字符串,并返回一个迭代器,需要用for循环获取其中的值,如:
import re
a1 = re.compile("bc") #编译好匹配对象,之匹配字符串bc
s1 = a1.finditer("abc123abc123xy1234")
for i in s1:
print(i.group()) 执行结果:
bc
bc #第二个bc是在字符串的中间也可以匹配到
5.fullmatch(pattern, string, flags=0):判断匹配的字符串和目标字符串是否完全一致,是返回匹配group()成功的字串,否返回None,如:
import re
s1 = re.fullmatch("password","password")
if s1:
print(s1.group(),"匹配成功")
else:
print("匹配失败") 执行结果:
password 匹配成功 #字符串完整匹配成功
6.match(pattern, string, flags=0):match只从开头匹配第一个字符串,第一个未匹配就不再继续向后匹配,即使后面可以匹配到也不继续匹配,其只从第一位匹配指定的字符串,如果连续匹配上算成功,如果有一个匹配不上即返回匹配失败并返回None:
在python术语中,主要有两种方法完成模式匹配,搜索(searching)和匹配(matching),搜索是在字符串中的任意位置搜索匹配的模式,而匹配是指判断一个字符串是否从起始位置就全部匹配或部分匹配的某个模式,搜索是通过search()函数或方法实现,而匹配是调用match()函数或方法实现的:
import re
s1 = re.match("","12nkaskd1") #match只从开头匹配第一个字符串,第一个未匹配就不再继续向后匹配,即使后面可以匹配到也不继续匹配
if s1:
print(s1.group(),"第一组匹配成功")
else:
print("s1匹配失败") s2 = re.match("","12034abc") #即使后面有0也不匹配,其只从第一位匹配指定的字符串,如果连续匹配上算成功,如果有一个匹配不上即返回匹配失败
if s2:
print(s2.group(),"第一组匹配成功")
else:
print("s2匹配失败") 执行结果;
7.purge():清空缓存中的正则表达式
import re
s1 = re.compile("password+=")
print(re.compile(s1))
print(re.purge()) 执行结果:
re.compile('password+=')
None
8.search(pattern, string, flags=0):search会从头到位匹配全部字符串当中是否有指定的字符串出现,在任意位置匹配成功都算成功,返回的是匹配成功的字符串:
search与findall的不同:
search是返回到的一个匹配到的结果,即使字符串当中有多个匹配结果也只返回一个,而且是返回的字符串格式
findall是返回的所有匹配结果,并将结果附加在一个列表当中
import re
s1 = re.search("","2nkaskd1") #search会从头到位匹配全部字符串当中是否有指定的字符串出现,在任意位置匹配成功都算成功
if s1:
print(s1.group(),"第一组匹配成功")
else:
print("s1匹配失败") s2 = re.search("","12bn1034abc") #在中间和结果匹配成功都算是匹配成功的
if s2:
print(s2.group(),"第一组匹配成功")
else:
print("s2匹配失败")
执行结果:
1 第一组匹配成功
10 第一组匹配成功
#######search与findall的不同:
import re
s1 = re.findall("ab","2nabkabcddopaoab") #search会从头到位匹配全部字符串当中是否有指定的字符串出现,在任意位置匹配成功都算成功
if s1:
print(s1,"第一组匹配成功")
else:
print("s1匹配失败") s2 = re.search("","10102bn1034ab10c") #在中间和结果匹配成功都算是匹配成功的
if s2:
print(s2.group(),"第一组匹配成功")
else:
print("s2匹配失败") 执行结果:
['ab', 'ab', 'ab'] 第一组匹配成功,findall是返回的所有匹配结果,并将结果附加在一个列表当中
10 第一组匹配成功,search是返回到的一个匹配打牌的结果,即使字符串当中有多个匹配结果也只返回一个,而且是返回的字符串格式
9.split(pattern, string, maxsplit=0, flags=0):split() 方法在用于在正则表达式中将字符串按照指定的分隔符进行切分,切分后将返回列表,方法同字符串的 split() 方法相似但提供更多的定界符,如:
import re
a1 = re.compile(r"\(")
s1 = a1.split("1+10-(10*3)") #search会从头到位匹配全部字符串当中是否有指定的字符串出现,在任意位置匹配成功都算成功
print(s1) 执行结果:
['1+10-', '10*3)'] #返回一个列表,以(对原字符串进行切分
10.sub(pattern, repl, string, count=0, flags=0):
import re
a1 = re.compile(r"jack") #提前编译正常表达式,指定替换的字符串为jack
s1 = a1.sub("tom","name is jack,name is jack,name is jack",count=2) #sub后面跟随将jack替换的目标字符串,和在哪里替换,可选参数count指定替换参数,默认为全部替换
s2 = a1.sub("tom","name is jack,name is jack,name is jack") #不指定替换次数
print(s1,"指定了2次替换")
print(s2,"未指定替换次数") 执行结果:
name is tom,name is tom,name is jack #指定了2次替换,超出次数一行将不再替换
name is tom,name is tom,name is tom 未指定替换次数
11.subn(pattern, repl, string, count=0, flags=0):subn() 方法类似于sub方法做字符串替换,但是返回的结果是替换后的一个元组,元组的前部分是替换后的结果,后部分是替换的次数,如:
import re
a1 = re.compile(r"jack") #提前编译正常表达式,指定替换的字符串为jack
s1 = a1.subn("tom","name is jack,name is jack,name is jack",count=2) #sub后面跟随将jack替换的目标字符串,和在哪里替换,可选参数count指定替换参数,默认为全部替换
s2 = a1.subn("tom","name is jack,name is jack,name is jack") #不指定替换次数
print(s1,"指定了2次替换")
print(s2,"未指定替换次数") 执行结果:
('name is tom,name is tom,name is jack', 2) 指定了2次替换
('name is tom,name is tom,name is tom', 3) 未指定替换次数
12.template(pattern, flags=0):和
import re
s1 = re.template("") #编译好要匹配的字串
print(s1.search("jack and tom is 21").group()) #对编译好的字串进行匹配 执行结果:
21 #只显示找到的字串
六:正则表达式匹配高级模式:
1.字符串匹配:
. :匹配任意单个字符,(换行符除外):
import re
print(re.match("2.","1+2-3*2+(4-4+1/3)")) #matc从0个元素匹配,一次成功即成功,不成功则失败并返回None,matc返回的是直接匹配结果,不需要使用group() 查看匹配到的内容 执行结果:
None #################
import re
print(re.search("2.","1+2-3*2+(4-4+1/3)").group()) #search匹配成功后只显示一个匹配结果,而且需要使用group查看匹配到的结果 执行结果:
2- ##################
import re
print(re.findall("1.","1+2-3*2+(4-4+1/3)")) #findall 会在整个字符串匹配,并以列表结果显示匹配到的所有的结果 执行结果:
['1+', '1/']
^ :从字符串的头部开始匹配,可以匹配是否以指定字符开头:
import re
print(re.findall("^1","1+2-3*2+(4-4+1/3)")) #search匹配成功后只显示一个匹配结果,而且需要使用group查看匹配到的结果 执行结果:
['']
$ :匹配字符串的结束,可以匹配是否已指定字符串结束:
import re
print(re.findall("1$","1+2-3*2+(4-4+1/3)-1"))
print(re.findall("1$","1+2-3*2+(4-4+1/3)-2"))#匹配是否已指定字符串结尾,是返回匹配结果.否返回空列表
执行结果:
['']
[]
* :匹配前一个字符出现了0次或多次,即前面的字符可以没有匹配到也可以有无数个,这种操作符也称为Kleene(闭包操作):
import re
print(re.findall("a*","1+a+b-2"))#匹配是否已指定字符串结尾,是返回匹配结果.否返回空列表 执行结果:
['', '', 'a', '', '', '', '', ''] #返回列表形式的结果,为匹配带的元素用空字串表示
+ :匹配前一个元素出现一次或多次,即至少要有一次,也可以有无数次,也被称为正闭包操作:
import re
print(re.findall("a+","1+aaaba+b-2"))#匹配是否已指定字符串结尾,是返回匹配结果.否返回空列表
执行结果:
['aaa', 'a']
? :匹配前一个字符出现0次或1次,即可以1个也没有,也可以有1个,但是后面就不会匹配了,因为只会匹配一个没有有一个,不负责匹配两个:
import re
print(re.findall("a?","1+aaaba+b-2"))#匹配是否已指定字符串结尾,是返回匹配结果.否返回空列表 执行结果:
['', '', 'a', 'a', 'a', '', 'a', '', '', '', '', ''] #单独匹配每个元素,未能匹配成功的元素以空字串表示
{N}:匹配前面的表达式指定次数,即强制匹配多少次:
import re
print(re.findall("a{3}","1+aaaba+b-2"),"#指定前面的字符匹配多少次,匹配结果放在列表当中")
print(re.findall("a{4}","1+aaaba+b-2"),"#指定前面的字符匹配多少次,超出范围后抛出空列表") 执行结果:
['aaa'] #指定前面的字符匹配多少次,匹配结果放在列表当中
[] #指定前面的字符匹配多少次,超出范围后抛出空列表
{M,N}: 匹配前面的字符出现M-N次
import re
print(re.findall("a{1,3}","1+aaaba+b-2"),"#指定前面的字符匹配多少到多少次,匹配结果分开放在列表当中")
print(re.findall("a{1,10}","1+aaaba+b-2"),"#指定前面的字符匹配多少到多少次,匹配结果分开放在列表当中,超出匹配范围不报错") 执行结果:
['aaa', 'a'] #指定前面的字符匹配多少次,匹配结果放在列表当中
['aaa', 'a'] #指定前面的字符匹配多少次,超出范围后抛出空列表
[xxx] :匹配字符串当中的任意一个字符:
import re
print(re.findall("a[abc]","1+aabbaba+b-2"),"匹配中括号当中的任意一个字符,即a后面可以是a可以是b也可以是c,中括号里的字符之间是或关系")
print(re.findall("b[abc]","1+babababab"),"匹配中括号当中的任意一个字符,字符是或关系")
执行结果:
['aa', 'ab'] 匹配中括号当中的任意一个字符,字符是或关系
['ba', 'ba', 'ba', 'ba'] 匹配中括号当中的任意一个字符,字符是或关系
[x-y]:匹配出现在中括号里的任意一个字符:
import re
print(re.findall("a[a-z]","1+aabbaba+b-2"),"匹配a-z当中的任意一个字符")
print(re.findall("b[b-d,f-z]","abacdbebz"),"匹配中括号当中b-d和f-z当中的字符,即把a和e不匹配,如此匹配则前方的ba和be都没有匹配到") 执行结果:
['aa', 'ab'] #匹配a-z当中的任意一个字符
['bz'] #匹配中括号当中b-d和f-z当中的字符,即把a和e不匹配,如此匹配则前方的ba和be都没有匹配到
[^x-y]:取反,凡是出现在里面的字符都不进行匹配:
import re
print(re.findall("a[^c-z]","1+aabbaba+b-2"),"匹配a-z当中的任意一个字符")
print(re.findall("b[^b-d,f-z]","abacdbebz"),"与上次完全相反,这次出现在里面的不匹配,不出现的却被匹配,本次只匹配a和e")
执行结果:
['aa', 'ab', 'a+'] 匹配a-z当中的任意一个字符
['ba', 'be'] 与上次完全相反,这次出现在里面的不匹配,不出现的却被匹配,本次只匹配a和e
[^xy]:不匹配出现在中括号里面的单个字符:
import re
print(re.findall("a[^bcd]","1+aabbaba+b-2"),"a后面凡是出现b或c胡或d都不匹配")
print(re.findall("b[^b,d-z]","abacdbcbebbz"),"b后面出现b,d-z的字符不匹配") 执行结果:
['aa', 'a+'] a后面凡是出现b或c胡或d都不匹配
['ba', 'bc'] b后面出现b,d-z的字符不匹配
():对表达式进行分组:
import re
s1 = re.match("(a(b)c)","abc") #对匹配进行分组,
print(s1.group(1),"分组1")
print(s1.group(2),"分组2")
print(s1.groups(),"所有分组") 执行结果:
abc 分组1
b 分组2
('abc', 'b') 所有分组
2.特殊字符匹配:
\d:匹配任何数字,和0-9效果一致:
import re
print(re.search("\da","abc1a").group()) #匹配任何一个数字后面跟了一个a 执行结果:
1a
\D:和\d完全相反,匹配任何非数字
import re
print(re.search("\Da","abc1!@a").group()) #查找特殊字符后面带a的 执行结果:
@a #匹配到的特殊字符
\w:匹配任何数字字母字符,同等于[0-9][a-z][A-Z]:
import re
print(re.search("\wa","wabc1!@a").group()) #匹配任何一种字母数字和字符后后面带a的 执行结果:
wa #匹配到的wa
\W:和\w完全相反,取[0-9][a-z][A-Z]以外的特殊字符:
import re
print(re.findall("\Wa","wrabc1!1@a"),"\W只会匹配数字和大小写字母以外的特殊字符")
print(re.findall("\Da","wrabc1!1@a"),"\D会匹配除数字以外的其他字符,包括字母和特殊字符") 执行结果:
['@a'] \W只会匹配数字和大小写字母以外的特殊字符
['ra', '@a'] \D会匹配除数字以外的其他字符,包括字母和特殊字符
\s:匹配任何空白字符,等于匹配\n \t \r \v \f:
import re
print(re.findall("\s","w rabc1!1@a"),"\s匹配空格")
print(re.findall("\s","wrabc 1!1@\na"),"\s匹配空格和换行符\n") 执行结果:
[' '] \s匹配到的空格元素
[' ', '\n'] \s匹配空格和换行符和空格
\S:与\s相反,匹配空白字符\n \t \r \v \f以外的字符
import re
print(re.findall("\S","w rabc1!1@a"),"\S匹配空白符以外的字符,中间的空格给忽略了")
print(re.findall("\S","wrabc 1!1@\na"),"\S匹配空白字符以外的字符,空格和\n给忽略了") 执行结果:
['w', 'r', 'a', 'b', 'c', '', '!', '', '@', 'a'] \S匹配空白符以外的字符,中间的空格给忽略了
['w', 'r', 'a', 'b', 'c', '', '!', '', '@', 'a'] \S匹配空白字符以外的字符,空格和
给忽略了
\b:匹配单词边界:
import re
print(re.findall(r"oy\b","tom jack is a boy!"),"匹配右侧是否单词边界,即有空格或其后面没有单词了,boy是最后一个单词")
print(re.findall(r"om\b","tom jack is a boy!"),"匹配右侧是否单词边界,即有空格或其后面没有单词了,om是tom,右侧是空格")
print(re.findall(r"\bom","tom jack is a boy!"),"om是tom,om的左侧还有一个t因此其左侧不是单词边界") 执行结果:
['oy'] 匹配右侧是否单词边界,即有空格或其后面没有单词了,boy是最后一个单词
['om'] 匹配右侧是否单词边界,即有空格或其后面没有单词了,om是tom,右侧是空格
[] om是tom,om的左侧还有一个t因此其左侧不是单词边界
\B:与\b相反,匹配非单词边界,即这个单词不是以此开头的:
import re
print(re.findall(r"oy\B","tom jack is a boy!"),"oy右侧是单词边界,因此不会匹配上")
print(re.findall(r"\Bom","tom jack is a boy!"),"om左侧不是单词边界,因此可以匹配成功")
print(re.findall(r"om\B","tom jack is a boy!"),"om右侧是边界,因此不会匹配成功") 执行结果:
[] oy右侧是单词边界,因此不会匹配上
['om'] om左侧不是单词边界,因此可以匹配成功
[] om右侧是边界,因此不会匹配成功
\nn:匹配已经保存的子组:
匹配手机号:
import re
a = "mail:xxxx@aa.xxx.com,TEL:18600033300"
b = "email:1669121886@qq.com"
print(re.findall(r"\d[0-9]{10}",a))
print(re.findall(r"\d[0-9]{10}",b)) 执行结果:
['']
[]
匹配邮箱地址:
import re
a = "mail:xxxx@aa.xxx.com,TEL:18600033300"
b = "email:1669121886@qq.com"
print(re.findall("\w+@\w+\.*\w+\.com",a)) #\w+\.* 匹配*前面的字符0次或多次,本次匹配三级域名邮箱
print(re.findall("\w+@\w+\.*\w+\.com",b)) #本次匹配两级域名的邮箱 执行结果:
['xxxx@aa.xxx.com']
['1669121886@qq.com']
match只从开头进行完整匹配,头部匹配成功才算成功,search相当于全行匹配,任意位置匹配成功都算成功,两种方法返回的是匹配到的对象,要使用group查看对象里面的结果
findall返回的是所有结果的一个列表,不需要使用group即可看到结果,也可以使用for循环遍历每一个元素
Python 第四篇:生成器、迭代器、装饰器、递归函数与正则表达式的更多相关文章
- Python-Day4 Python基础进阶之生成器/迭代器/装饰器/Json & pickle 数据序列化
一.生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面 ...
- Python之旅Day5 列表生成式 生成器 迭代器 装饰器
装饰器 器即函数,装饰即修饰,意指为其他函数添加新功能 装饰器定义:本质就是函数,功能是为其他函数添加新功能 装饰器涉及的知识点= 高阶函数+函数嵌套+闭包 在遵循下面两个原则的前提下为被装饰者新功能 ...
- python基础(八)生成器,迭代器,装饰器,递归
生成器 在函数中使用yield关键字就会将一个普通的函数变成一个生成器(generator),普通的函数只能使用return来退出函数,而不执行return之后的代码.而生成器可以使用调用一个next ...
- python成长之路【第四篇】:装饰器
实现装饰器的知识储备: 示例: def f1(): print("f1") 1.函数即“变量” #上面的示例中,函数f1为变量,它指向内存地址.而f1()表示函数执行. 2.高阶函 ...
- Python 闭包、迭代器、生成器、装饰器
Python 闭包.迭代器.生成器.装饰器 一.闭包 闭包:闭包就是内层函数对外层函数局部变量的引用. def func(): a = "哈哈" def func2(): prin ...
- python的迭代器、生成器、装饰器
迭代器.生成器.装饰器 在这个实验里我们学习迭代器.生成器.装饰器有关知识. 知识点 迭代器 生成器 生成器表达式 闭包 装饰器 实验步骤 1. 迭代器 Python 迭代器(Iterators)对象 ...
- python is、==区别;with;gil;python中tuple和list的区别;Python 中的迭代器、生成器、装饰器
1. is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同 == 比较的是两个对象的内容是否相等 2. with语句时用于对try except finally 的优 ...
- Python3基础教程(十六)—— 迭代器、生成器、装饰器
在这个实验里我们学习迭代器.生成器.装饰器有关知识. 这几个概念是 Python 中不容易理解透彻的概念,务必把所有的实验代码都完整的输入并理解清楚其中每一行的意思. 迭代器 Python 迭代器(I ...
- Day4- Python基础4 深浅拷贝、三目运算、列表生成式,迭代器&生成器、装饰器
本节内容: 1.深浅拷贝 2.三目运算 3.迭代器和生成器 4.装饰器 1.深浅拷贝 拷贝意味着对数据重新复制一份,深浅拷贝的含义就是:对于修改复制的数据是否会影响到源数据,拷贝操作对于基本数据结构需 ...
随机推荐
- 讲讲金融业务(一)--自助结算终端POS
之前在群里和大家聊天的时候,发现好多人对银行业务比較感兴趣,或许是由于大家对银行不了解,以为非常神奇的样子.全部,从这周開始我打算把我肚子里的墨水慢慢地倒出来,和大家分享分享. 在技术还不发达的时 ...
- Ext.MessageBox.Show使用Progress
在此之前,先添加引用:以下引用方式仅供参考:由于我的extjs文件夹放在script文件夹下 <link href="~/Scripts/extjs/resources/ext-the ...
- IOS中的自动布局
Autolayout是一种“自动布局”技术,专门用来布局UI界面 Autolayout能很轻松地解决屏幕适配问题 Autolayout的两条核心概念: >1 参照:通过参照其他控件或父控件来 ...
- tcpdump使用技巧
tcpdump使用技巧 http://www.veryarm.com/1751.html
- BZOJ 4260: Codechef REBXOR( trie )
求出前缀和, 那么以第x个元素结尾的最大异或值是max(sumx^sump)(1≤p<x), 用trie加速. 后缀同理, 然后扫一遍就OK了.时间复杂度O(31N) ------------- ...
- 纯css画哆啦A梦
今天有点无聊,照着网上的图写了个哆啦A梦,无技术可言,纯考耐心. <!doctype html> <html lang="en"> <head> ...
- seajs + easyui [转]
* *content seajs+easyui使用 */ /** * 首先来看看在seajs中jquery和jquery插件如何使用 */ 1.jquery.js define(function(re ...
- Spring (一) IOC ( Inversion Of Control )
前序 现在小米手机很火就还拿小米手机来举例子,上一篇写的关于SSH框架搭建是从小米手机公司内个整个流程方面来考虑,如何提高效率生产效率,这篇博客主要从公司外部环境说明如何提高生产效率,那么怎么才能提高 ...
- map,area标签
map,area标签 <img src ="planets.gif" alt="Planets" usemap ="#planetmap&quo ...
- PHP - 直接输出对象的版本问题