Python_Day6_反射_正则表达式之篇
一、反射
定义:利用字符串形式去对象(模块)中操作(寻找/检查/删除/设置)成员
#getattr:获取模块中属性
#hasattr:检查模块中是否存在某个成员(函数)
#delattr:删除模块中成员
#setattr:设置某块中
一般常用反射模式:
import fanshe_commons #导入访问函数的模块【fanshe_commons模块中设置有login,logout,home等函数】
def run():
inp = input("请输入访问URL:")
if inp == 'login': #
fanshe_commons.login() #调用fanshe_commons模块中login函数,当输入输入URL为login时,执行login函数,此时比忘记执行函数要带login()
elif inp == 'logout':
fanshe_commons.logout()
elif inp == 'home':
fanshe_commons.home()
else:
print("404")
if __name__ == '__main__': #if __name__ == '__main__'表示只在当前模块执行主函数
run()
反射阶级02:
hasattr:检查模块中是否存在某个成员(函数)
#getattr:获取模块中属性
import fanshe_commons ##导入访问函数的模块 fanshe_commons某块中含有login,logout,home函数
def run():
inp =input("请输入要访问的URL:")#inp属于一个字符串,那么fanshe_commons.inp() != fanshe_commons.login()
if hasattr(fanshe_commons,inp): # #hasattr:检查模块中是否存在某个成员(函数)
func = getattr(fanshe_commons,inp) #getattr:获取模块中属性
func()
else:
print("404")
if __name__ == '__main__':
run()
反射阶级03:
应用“_import_”方法:可以对多个模块中的方法进行调用,不需挨个挨个通过import导入某块
格式:#模块/方法
import fanshe_commons ##导入访问函数的模块 fanshe_commons某块中含有login,logout,home函数
def run():
#commons/login 注意:在输出方式也需要按照“某块/方法”进行
inp =input("请输入要访问的URL:")#inp属于一个字符串,那么fanshe_commons.inp() != fanshe_commons.login()
m,f = inp.split('/') #将mn比作为一个模块,f为这个模块下的函数或者成员
obj = __import__(m) #将模赋值给一个值
if hasattr(obj,f): # #hasattr:检查模块中是否存在某个成员(函数)
func = getattr(obj,f) #getattr:获取模块中属性
func()
else:
print("404")
if __name__ == '__main__':
run()
阶级04:在不同的文件夹中导入函数
# obj = __import__("lib."+m,fromlist=True) #导入两个不同的文件夹中的函数[fromlist=True:表示将两个文件夹中链接进行拼接在一起]
import fanshe_commons ##导入访问函数的模块 fanshe_commons某块中含有login,logout,home函数
def run():
#commons/login 注意:在输出方式也需要按照“某块/方法”进行
inp =input("请输入要访问的URL:")#inp属于一个字符串,那么fanshe_commons.inp() != fanshe_commons.login()
m,f = inp.split('/') #将m比作为一个模块,f为这个模块下的函数或者成员
# obj = __import__(m) #将模赋值给一个值
obj = __import__("lib."+m,fromlist=True) #导入两个不同的文件夹中的函数
if hasattr(obj,f): # #hasattr:检查模块中是否存在某个成员(函数)
func = getattr(obj,f) #getattr:获取模块中属性
func()
else:
print("404")
if __name__ == '__main__':
run()
扩展
几种常见的导入模块方式有:
A:import XXX模块
B: from xxx文件夹 import +方法
C:obj = _import_("模块")
D:obj = _import_("文件夹.oo.xx",fromlist=True)
二、hashlib:加密
用于加密相关的操作,代替了MD5模块和sha模块,主要提供了SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法
#文件加密,md5不可反解密,如果要比较md5值,可将两个密码加密至密文进行比较,同一个密码的密文是相等
#update('xxxx'):python2.7中表示对xx进行加密
#update(byte('1243')) :python3.0之后将字符串变成字节方式进行加密
#hexdigest():获取加密的值
obj =hashlib.md5(bytes('dsdsdssdjkjkjfjsd',encoding='utf-8')) #创建md5,并通过bytes进行第一次加密,防止撞库
obj.update(bytes('123',encoding ='utf-8')) #通过update对123进行再一次加密
result = obj.hexdigest() #获取加密的值
print(result)
其他加密算法:
hash =hashlib.sha256()
hash.update(bytes('123',encoding='utf-8'))
print(hash.hexdigest())
hash =hashlib.sha384()
hash.update(bytes('123',encoding='utf-8'))
print(hash.hexdigest())
hash =hashlib.sha512()
hash.update(bytes('123',encoding='utf-8'))
print(hash.hexdigest())
# 058bb0ac0ca843c6187ec32716d67f5f
# a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
# 9a0a82f0c0cf31470d7affede3406cc9aa8410671520b727044eda15b4c25532a9b5cd8aaf9cec4919d76255b6bfb00f
# 3c9909afec25354d551dae21590bb26e38d53f2173b8d3dc3eee4c047e7ab1c1eb8b85103e3be7ba613b31bb5c9c36214dc9f14a42fd7a2fdb84856bca5c44c2
以上算法虽然厉害,但存在缺陷,即:可以通过撞库进行反解,所以,有必要对加密算法中自定义添加key再来做加密
#文件加密,md5不可反解密,如果要比较md5值,可将两个密码加密至密文进行比较,同一个密码的密文是相等 #update('xxxx'):python2.7中表示对xx进行加密 #update(byte('1243')) :python3.0之后将字符串变成字节方式进行加密 #hexdigest():获取加密的值
import hashlib obj =hashlib.md5(bytes('dsdsdssdjkjkjfjsd',encoding='utf-8')) #创建md5,并通过bytes进行第一次加密,防止撞库 obj.update(bytes('123',encoding ='utf-8')) #通过update对123进行再一次加密 result = obj.hexdigest() #获取加密的值 print(result)
python内置模块还提供一个hmac模块,它内部对我们创建Key和内容进行第一次的处理然后在进行加密
import hmac
key = hmac.new(bytes('sdfewvdf323dfdsd',encoding='utf-8')) #创建加密key并对key进行第一次加密
key.update(bytes('123',encoding='utf-8')) #将字符串123进行加密
print(key.hexdigest()) #获取加密值
三、正则表达式 re
python中re模块提供了正则表达式相关操作:
字符:
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
次数:
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
简介:
就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
1、字符匹配包含:普通字符,元字符
1)、普通字符:大多数字符和字母都会和自身匹配
import re
#findall:查找当前所有字符串进行查找
#"lcj":需要匹配的规则,从左向右
print(re.findall("lcj",'dsidusdusdolcjdsdslcjlcjlcj'))
# ['lcj', 'lcj', 'lcj', 'lcj']
2)元字符:
常用元字符包含:^ $ * + ? {} [] | () \
我们首先考察的元字符是"[" 和 "]"。它们常用来指定一个字符类别,所谓字符类别就是你想匹配的一个字符集。字符可以单个列出,也可以用“-”号分隔的两个给定字符来表示一个字符区间。例如,[abc] 将匹配"a", "b", 或 "c"中的任意一个字符;也可以用区间[a-c]来表示同一字符集,和前者效果一致。如果你只想匹配小写字母,那么 RE 应写成 [a-z].元字符在类别里并不起作用。例如,[akm$]将匹配字符"a", "k", "m", 或 "$" 中的任意一个;"$"通常用作元字符,但在字符类别里,其特性被除去,恢复成普通字符。
[]:元字符[]表示字符类,在一个字符类中,只有字符^、-、]和\有特殊含义。
字符\仍然表示转义,字符-可以定义字符范围,字符^放在前面,表示非.
+ 匹配+号前内容1次至无限次
? 匹配?号前内容0次到1次
{m} 匹配前面的内容m次
{m,n} 匹配前面的内容m到n次
*?,+?,??,{m,n}? 前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
\:特殊功能
反斜杠后边跟元字符去除特殊功能,
反斜杠后边跟普通字符实现特殊功能。
引用序号对应的字组所匹配的字符串
re.search(r"(alex)(eric)com\2","alexericcomeric")
\d 匹配任何十进制数;它相当于类 [0-9]。
\D 匹配任何非数字字符;它相当于类 [^0-9]。
\s 匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
\b: 匹配一个单词边界,也就是指单词和空格间的位置。
匹配单词边界(包括开始和结束),这里的“单词”,是指连续的字母、数字和下划线组成的字符串。注意,\b的定义是\w和\W的交界,这是个零宽界定符(zero-width assertions)只用以匹配单词的词首和词尾。单词被定义为一个字母数字序列,因此词尾就是用空白符或非字母数字符来标示的。
# .表示除换行符之外的所有字符都能匹配到,且执行匹配一个字符
# .表示除换行符之外的所有字符都能匹配到,且执行匹配一个字符 print(re.findall("l.j",'dsidusdusdolcjdsds')) # ['lcj']
#添加换行符\:时,.匹配为空
print(re.findall("l.j",'dsidusdusdolc\jdsds'))
# []
#^:表示以某某开头,即只匹配开头的字符,中间的字符不匹配
#^:表示以某某开头,即只匹配开头的字符,中间的字符不匹配
print(re.findall('^l.j','lcjdsidusdusdolcjdsds'))
# ['lcj']
#$:表示匹配字符串中末尾的字符
#$:表示匹配字符串中末尾的字符
print(re.findall('lcj$','lcjdsidusdusdolcjdsdslcj'))
# ['lcj']
# * + ? {} 匹配多个字符
#*:匹配*前面字符0到多次
#*:匹配*前面字符0到多次
print(re.findall('l.*j','lccfdfdcssjdsidusdusdodsds'))
# ['lccfdfdcssj']
print(re.findall('l.*j','cfdfdcssjdsiljdusdusdodsds')) #匹配字符中间为空也能匹配到字符
#['lj']
# +:匹配1到多次
# +:匹配1到多次
print(re.findall('l.+j','dsiljdusdusdodsds')) #表示:匹配规则中必修含有一个匹配的字符,否则就匹配不到
#[]
# ?:匹配0到1次,
# ?:匹配0到1次,
print(re.findall('l.?j','dsiljdusdusdodsds'))
# ['lj']
print(re.findall('l.?j','dsilcjdusdusdodsds'))
#['lcj']
print(re.findall('l.?j','dsilcdjdusdusdodsds')) #lcdj:匹配规则是0和1,此时字符串中有两位cd,即匹配不到,返回空
# []
#{}:匹配多次
#{}:匹配多次
print(re.findall('l.{3}j','dsilcwwjdusdusdodsds')) #匹配三个字符
# ['lcwwj']
print(re.findall('l.{1,3}j','dsilcwjdusdusdodsds')) #匹配一个范围之内的字符,超过批次的字符及匹配不到,返回[]
# ['lcwj']
print(re.findall('ld{1,3}j','dsilddjdusdusdodsds'))#大括号只匹配前面字符d次数为1-3次,超过匹配次数及返回[]
# ['lddj']
#[]:或的作用
print(re.findall('l[cd]j','lcj'))
# ['lcj']
print(re.findall('l[cd]j','ldj'))
# ['ldj']
print(re.findall('l[a-z]j','lfj')) #匹配a-z中间的任意一个字符,不能匹配多个字符
# ['lfj']
print(re.findall('l[a-z]j','lfdj'))
# []
print(re.findall('l[a-z]+j','lfdj'))#+:匹配前面字符集
# ['lfdj']
#元字符:^ * . ? {}在中括号中指标是普通的匹配规则字符
#元字符:^ * . ? {}在中括号中指标是普通的匹配规则字符
print(re.findall('l[a*]j','lfdj'))
# []
print(re.findall('l[a*]j','laj'))
# ['laj'] 在字符串中只匹配a或者*,不能同时匹配a*
#: - :在中括号好表示匹配多个字符,但—只匹配一个字符串
#: - :在中括号好表示匹配多个字符,但—只匹配一个字符串
print(re.findall('l[a-z]j','lfj'))
# ['lfj']
print(re.findall('l[0-9]j','l2j'))
# ['l2j']
# ^:在中括号中表示“非”的意思,不在表示已某某开头
# ^:在中括号中表示“非”的意思,不在表示已某某开头
print(re.findall('l[^d]j','lgj'))
# ['lgj']
# \d:在中括号中匹配任意一个数字
# \d:在中括号中匹配任意一个数字
print(re.findall('l[\d]j','l0j'))
# ['l0j']
#\b:匹配一个单词边界,即单词和空格之间的位置
#\b:匹配一个单词边界,即单词和空格之间的位置
print(re.findall(r'I\b',' I am I lcj'))
# ['I', 'I']
#\b:匹配一个单词边界,即单词和空格之间的位置
#\b:匹配一个单词边界,即单词和空格之间的位置
print(re.findall(r'I\b',' I am I lcj'))
# ['I', 'I']
print(re.findall(r'I\b',' I&am I lcj'))#匹配单个单词可以用非字母数字符来标示的【& % @ # $ ^】。
# ['I', 'I']
四、函数
1、match:从起始位置开始匹配,匹配成功返回一个对象,未匹配成功则返回None
格式:re.match(pattern, string, flags=0) 【pattern:匹配正则规则模型,string:要匹配的字符串,flags:匹配模式,编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。】
#格式:match:re.match(pattern, string, flags=0)
#flags: 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
#match按照匹配规则匹配字符串起始位置,并发返回匹配结果
ret= re.match('lcj','lcjwww,runlcj.com')
print(ret)
# <_sre.SRE_Match object; span=(0, 3), match='lcj'> #获取返回结果值
ret= re.match('lcj','lcjwww,runlcj.com').group()#.group()将匹配的结果取出
print(ret)
正则分组:提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)
origin = 'shs fifr44k44657666jfdkds'
#无分组 r = re.match('s\w+',origin) #\w 匹配字母或数字或下划线或汉字,+:重复一次或多次 print(r.group())#获取所有匹配到的结果 # shs
#有分组 r = re.match('s(\w+)',origin) print(r.groups()) #获取模型中分组的结果 # ('hs',) 返回分组结果值 r = re.match('s(?P<name>\w+)',origin) #对获取分组结果值设置一个key值,即key值等于分组返回的结果,\w 匹配任何字母数字字符,+:匹配+号前内容1次至无限次 print(r.groupdict()) #获取 # {'name': 'hs'}
注意:
re.match('com', 'comwww.runcomoob')
re.search('\dcom', 'www.4comrunoob.5com')
一旦匹配成功,就是一个match object 对象,而match object 对象拥有以下方法:
group() 返回被 RE 匹配的字符串
start() 返回匹配开始的位置
end() 返回匹配结束的位置
span() 返回一个元组包含匹配 (开始,结束) 的位置
group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。
1. group()返回re整体匹配的字符串,
2. group (n,m) 返回组号为n,m所匹配的字符串,如果组号不存在,则返回indexError异常
3.groups()groups() 方法返回一个包含正则表达式中所有小组字符串的元组,从 1 到
所含的小组号,通常groups()不需要参数,返回一个元组,元组中的元就是正则
表达式中定义的组。
import re
a = "123abc456"
re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0) #123abc456,返回整体
re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1) #123
re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2) #abc
re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3) #456
group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3)
列出第三个括号匹配部分。
2、findall
获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;
import re
hh = 'fdrsf jdu fdr43f 435h34h'
#无分组
ret = re.findall('f\w+f',hh)
# ['fdrsf', 'fdr43f'] 在返回无分组数字
print(ret)
#有分组
ret = re.findall('f(\w+)f',hh) #获取单个分组返回的数字
print(ret)
# ['drs', 'dr43'] #返回分组数字
ret = re.findall('f(\w+)r(\w+)f',hh)#获取两个分组返回的数字
print(ret)
# [('d', 's'), ('d', '43')] #返回分组数字
3、search
#search:游览整个字符串并去匹配第一个,未匹配则返回一个None
格式:# search(pattern, string, flags=0)
#search:游览整个字符串并匹配第一个,未匹配则返回一个None
ret= re.search('lcj','www,runlcj.com')
print(ret)
# <_sre.SRE_Match object; span=(7, 10), match='lcj'> #获取返回结果值
ret= re.search('lcj','www,runlcj.com').group()#.group()将匹配的结果取出
print(ret)
search分组
#ret.group() #获取匹配到的所有结果
#ret.groups() #获取模型中匹配到的分组结果
#ret.groupdict() #将匹配的字符串设置一个key,(?P<name>\w+)形式,获取模型中匹配到的分组中所有执行了key的组
#search:游览整个字符串并匹配第一个,未匹配则返回一个None
ret= re.search('lcj','www,runlcj.com')
print(ret)
# <_sre.SRE_Match object; span=(7, 10), match='lcj'> #获取返回结果值
ret= re.search('lcj','www,runlcj.com').group()#.group()将匹配的结果取出
print(ret)
ret = re.search('lcj','lcjwww,runlcj.com')#返回第一个匹配的字符串
print(ret.group())
# lcj
ret = re.search('(lcj)','lcjwww,runlcj.com')
print(ret.groups())#将括号中的分组数字返回
# ('lcj',)
ret = re.search('l(?P<name>\w+)r','lcjwwwrunlcjcom')#\w 匹配字母或数字或下划线或汉字,+:匹配+号前内容1次至无限次
print(ret.groupdict()) #给匹配的字符设置一个key,即key就登入获取的返回结果值
# {'name': 'cjwww'}
4、findall:
re.findall 以列表形式返回所有匹配的字符串
获取非常复杂的匹配列表,如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果有多个组,则以列表形式返回,且每一个匹配均是元祖
空的匹配也会包含在结果中
格式:#findall(pattern, string, flags=0)
#finall 把所有匹配的字符串取出 # re.findall 以列表形式返回所有匹配的字符串 # re.findall可以获取字符串中所有匹配的字符串
#无分组 ret = re.findall('lcj','lcjdsddddlcj,dsdlcj') print(ret) # ['lcj', 'lcj', 'lcj'] ret = re.finditer('lcj','lcjdsddddlcj,dsdlcj')#finditer返回匹配到的一个对象 print(ret)
#有分组
ret = re.findall('lcj','lcjdsddddlcj,dsdlcj') #匹配字符串中所有lcj
print(ret)
# ['lcj', 'lcj', 'lcj']
ret = re.findall('l(c)j','lcjdsddddlcj,dsdlcj')#按照匹配到所有的字符串C进行分组
print(ret)
# ['c', 'c', 'c']
ret = re.findall('l(\w+)j','lcjdsddddlcj,dsdlcj')#匹配l-j之间所有的字符,并将结果以一个列表形式返回给分组
print(ret)
5、sub subn:匹配字符串
#格式:re.sub(pattern, repl, string, count
=
0
,
flags
=
0
) :pattern:正规模型,repl:需替换的字符串或可执行对象,string:需要匹配的字符串,count
=
0
:匹配次数,flags
=
0
:匹配模式
于无分组无关
#格式:re.sub(pattern, repl, string, max=0) :pattern:匹配规则,repl:需替换的字符串
ret = re.sub("g.t","have",'I get A, I got B ,I gut C')
print(ret)
# I have A, I have B ,I have C
#2:表示最大替换次数
ret = re.sub("g.t","have",'I get A, I got B ,I gut C',2)#将g.t字符串替换成have
print(ret)
# I have A, I have B ,I gut C
#subn:将替换的次数打印出
ret = re.subn("g.t","have",'I get A, I got B ,I gut C',2)
print(ret)
# ('I have A, I have B ,I gut C', 2)
6、splist
#split 根据 匹配规则进行分割
#split:分割
ret=re.split('\d+','one1two2three3four4')#\d:1到多个数字,从左往右按照阿拉伯数字进行分割,且
print(ret)
# ['one', 'two', 'three', 'four', '']
分组
import re
kw = "dfdsd lcj s224 lcj fr334"
#无分组,匹配到数字,但没有取已经匹配到的数字
ret=re.split('lcj',kw,1) # 1:表示按照匹配的第一个进行分割
print(ret)
# ['dfdsd ', ' s224 lcj fr334']
#有分组,当有多个分组时,先匹配最外面的分组,在匹配里面的分组
ret=re.split('l(c)j',kw,1) #
print(ret) #将已匹配到字符串打印出
# ['dfdsd ', 'c', ' s224 lcj fr334']
ret=re.split('(lcj)',kw,2)
print(ret)
# ['dfdsd ', 'lcj', ' s224 lcj fr334']
7、compile
格式:re.compile(strPattern[, flag]):
这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。 第二个参数flag是匹配模式,取值可以使用按位或运算符'|'表示同时生效,比如re.I | re.M 可以把正则表达式编译成一个正则表达式对象。可以把那些经常使用的正则表达式编译成正则表达式对象,这样可以提高一定的效率。下面是一个正则表达式
#re.compile(strPattern[, flag]):strPattern:对象,flag:匹配规则,
text = "JGood is a handsome boy, he is cool, clever, and so on..."
#将规则封装成一个对象,每次调用可直接调用该对象
regex = re.compile(r'\w*oo\w*') #\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
print (regex.findall(text)) #查找所有包含'oo'的单词
#['JGoo', 'coo']
推荐:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
注意:【原生字符串与特殊字符关系】
你可能已经看到前面关于原始字符串用法的一些例子了。原始字符串的产生正是由于有正则表达式的存在。原因是ASCII 字符和正则表达式特殊字符间所产生的冲突。比如,特殊符号“\b”在ASCII 字符中代表退格键,但同时“\b”也是一个正则表达式的特殊符号,代表“匹配一个单词边界”。为了让RE 编译器把两个字符“\b”当成你想要表达的字符串,而不是一个退格键,你需要用另一个反斜线对它进行转义,即可以这样写:“\\b”。但这样做会把问题复杂化,特别是当你的正则表达式字符串里有很多特殊字符时,就更容易令人困惑了。原始字符串就是被用于简化正则表达式的复杂程度。事实上,很多Python 程序员在定义正则表达式时都只使用原始字符串。下面的例子用来说明退格键“\b” 和正则表达式“\b”(包含或不包含原始字符串)之间的区别:
>>> m = re.search('\bblow', 'blow') # backspace, no match #退格键,没有匹配
>>> re.search('\\bblow', 'I blow').group() # escaped \, now it works #用\转义后,现在匹配了
>>> re.search(r'\bblow', 'I blow').group() # use raw string instead #改用原始字符串
你可能注意到我们在正则表达式里使用“\d”,没用原始字符串,也没出现什么问题。那是因为ASCII 里没有对应的特殊字符,所以正则表达式编译器能够知道你指的是一个十进制数字
ret = re.search(r'\bblow','blow') #\b匹配一个单词边界
print(ret)
# <_sre.SRE_Match object; span=(0, 4), match='blow'>
ret = re.search('\\bblow','blow')#
print(ret)
# <_sre.SRE_Match object; span=(0, 4), match='blow'>
【python正则表达式参考地址:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html#undefined】