Python基础(十)re模块
Python基础阶段快到一段落,下面会陆续来介绍python面向对象的编程,今天主要是补充几个知识点,下面开始今天的内容。
一、反射
反射的作用就是列出对象的所有属性和方法,反射就是告诉我们,这个对象到底是什么,提供了什么功能,
可以伪造Web框架的路由系统。
举个例子:
1
2
|
>>> dir (json) [ 'JSONDecodeError' , 'JSONDecoder' , 'JSONEncoder' , '__all__' , '__author__' , '__builtins__' , '__cached__' , '__doc__' , '__file__' , '__loader__' , '__name__' , '__package__' , '__path__' , '__spec__' , '__version__' , '_default_decoder' , '_default_encoder' , 'decoder' , 'dump' , 'dumps' , 'encoder' , 'load' , 'loads' , 'scanner' ] |
如上所看,dir是一个内置的反射函数,可以列出对象的属性和方法。那么看一下有哪些反射内置函数
-
dir([obj]): 调用这个方法将返回包含obj大多数属性名的列表(会有一些特殊的属性不包含在内),obj的默认值是当前的模块对象
-
hasattr(obj,attr): 这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。
-
getattr(obj,attr): 调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为'bar'则返回obj.bar.
-
setattr(obj,attr,val): 调用这个方法给obj的名为attr的值的属赋值为val,例如如果attr为'bar',则相当于obj.bar=val
下面举个例子来把上面的内置函数应用到实际环境中:
1
2
3
4
5
6
7
8
9
10
|
#!/usr/bin/env python def login(): print ( '欢迎登录' ) def out(): print ( 'exit....' ) def home(): print ( '你好' ) |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import commands #引用上面的自定义模块 def run(): inp = input ( '请输入访问的URL:' ) m,f = inp.split( '/' ) #输入时的格式为commands/方法 obj = __import__ (m) #获取用户输入的模块名,通过__import__(字符串)导入模块 if hasattr (obj,f): #判断模块里有没有输入方法 func = getattr (obj,f) #如果模块里有这个方法,获取模块里的方法 func() else : print ( '\033[31;1m404\033[0m' ) if __name__ = '__main__' : run() |
从上面的脚本里可以看到有一些想这种__import__、__name__、__main__的函数,下面我们来介绍一下这种函数:
-
__name__: 只有执行当前文件时,当前文件的特殊变量__name__=='__main__'才会生效,一般这个函数用到主函数中;
-
__file__: 当前py文件所在相对路径,要和os.path.abs()配合使用;
-
__cached__: 字节码存放位置pyc文件;
-
__import__(字符串): 可以通过__import__()函数导入模块;
-
__dic__: 获取程序注释
-
__package__:模块在包里面
二、hashlib加密模块
用于加密相关的操作,代替了md5和sha模块,主要提供SHA1、SHA224、SHA256、SHA384、SHA512、MD5算法。这里只介绍md5加密,下面请看例子:
1
2
3
4
5
6
7
8
9
10
|
import hashlib hash = hashlib.md5() hash .update(bytes( 'admin' ,encoding = 'utf-8' )) print ( hash .hexdigest()) print ( hash .digest()) #结果: 21232f297a57a5a743894a0e4a801fc3 b '!#/)zW\xa5\xa7C\x89J\x0eJ\x80\x1f\xc3' |
以上加密算法虽然依然非常厉害,但存在缺陷,即:通过撞库可以反解,所以有必要对加密算法中添加自定义key做二次加密。
1
2
3
4
5
6
7
8
9
|
import hashlib hash = hashlib.md5(bytes( '898oaFs09f' ,encoding = 'utf-8' )) hash .update(bytes( 'admin' ,encoding = 'utf-8' )) #对admin字符进行md5加密 print ( hash .hexdigest()) #结果: 67929daefab29024d18340945036e291 |
三、re模块
python中re模块提供了正则表达式相关操作。
1、 字符串匹配:
-
. 匹配除换行符以外的任意字符
-
\w 匹配字符或数字或下划线或汉字
-
\s 匹配任意空白字符
-
\d 匹配数字
-
\b 匹配单词的开始或结束
-
^ 匹配字符串的开始
-
$ 匹配字符串的结束
2、字符串次数匹配:
-
* 重复0次或多次
-
+ 重复1次或多次
-
? 重复0次或1次
-
{n} 重复n次
-
{n,} 重复n次或更多次
-
{n,m} 重复n到m次
3、re模块的方法
方法一:match
match:从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None.
1
2
3
4
|
#格式:re.match(pattern,string,flags=0) # pattern: 正则模型 # string:要匹配的字符串 # flags:匹配模式 |
举例说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#无分组 import re str = 'hello,jack123' r = re.match( 'h\w+' , str ) print (r.group()) #获取匹配到的所有结果 print (r.groups()) #获取模型中匹配到的分组结果 print (r.groupdict()) #匹配模型中匹配到的分组结果 #结果: hello #有分组 #分组:为了提取匹配成功的指定内容(先匹配成功全部正则,然后再将匹配成功的局部内容提取出来) r1 = re.match( 'h(?P<name>\w+).*k(\d+)' , str ) print (r1.group()) #获取匹配到的所有结果 print (r1.groups()) #获取模型中匹配到的分组结果 print (r1.groupdict()) #获取模型中匹配到的分组中所有 执行了key的组 #结果: hello,jack123 ( 'ello' , '123' ) { 'name' : 'ello' } |
方法二:search
search: 浏览整个字符串去匹配第一个,为匹配成功返回None,这里强调一下match方法是从开头去匹配。
格式: search(pattern,string,flags=0)
举例说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import re str = '123hello,jack123' #无分组 r = re.search( 'h\w+' , str ) print (r.group()) #获取匹配到的所有结果 print (r.groups()) #获取模型中匹配到的分组结果 print (r.groupdict()) #获取模型中匹配到的分组结果 #结果: hello () {} #有分组 r = re.search( 'h(?P<name>\w+).*k(?P<age>\d+)' , str ) print (r.group()) #获取匹配到的所有结果 print (r.groups()) # 获取模型中匹配到的分组结果 print (r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组 #结果: hello,jack123 ( 'ello' , '123' ) { 'age' : '123' , 'name' : 'ello' } |
方法三:findall
findall:获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中多个组,则以列表形式返回,且每一个匹配均是元组;空的匹配也会包含在结果中。
格式:findall(pattern,string,flags=0)
举例说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import re str = '123hello,jack123' #无分组 r = re.findall( 'h\w+' , str ) print (r) #结果: [ 'hello' ] #有分组 r1 = re.findall( 'h(\w+)' , str ) print (r1) #结果: [ 'ello' ] |
方法四:sub
sub:替换匹配成功的指定位置的字符串
1
2
3
4
5
6
|
#格式:sub(pattern,repl,string,count=0,flags=0) #pattern:正则模型 #repl :要替换的字符串或可执行对象 #string :要匹配的字符串 #count :指定匹配个数 #flags :匹配模式 |
举例说明:
1
2
3
4
5
6
7
8
|
import re str = '123hello,jack123hello' r = re.sub( "h\w+" , '456' , str , 1 ) #将字符串hello替换成456,后面这个flags=1是匹配到结果后,如果是多个只替换一个,默认是全部替换 print (r) #结果: 123456 ,jack123hello |
方法五:split
split:根据正则匹配分割字符串
1
2
3
4
5
|
#格式:split(pattern, string, maxsplit=0, flags=0) # pattern: 正则模型 # string : 要匹配的字符串 # maxsplit:指定分割个数 # flags : 匹配模式 |
举例说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
import re str = '123hello,jack123hello' #无分组 r = re.split( 'hello' , str , 1 ) print (r) #结果: [ '123' , ',jack123hello' ] #有分组 r1 = re.split( '(hello)' , str , 1 ) print (r1) r2 = re.split( '(h(ell)o)' , str , 1 ) #可以通过括号多切分几层,取到自己满意的结果为止 print (r2) #结果: [ '123' , 'hello' , ',jack123hello' ] [ '123' , 'hello' , 'ell' , ',jack123hello' ] |
1
2
3
4
5
6
7
|
inpp = '1-2*((60-30 +(-40-5)*(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))' inpp = re.sub( '\s*' ,'',inpp) #将空格替换成空 new_content = re.split( '\(([\+\-\*\/]?\d+[\+\-\*\/]?\d+){1}\)' , inpp, 1 ) print new_content #结果: [ '1-2*((60-30+' , '-40-5' , '*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))' ] |
练习:
1、拼接IP地址:
1
|
^( 25 [ 0 - 5 ]| 2 [ 0 - 4 ]\d|[ 0 - 1 ]?\d?\d)(\.( 25 [ 0 - 5 ]| 2 [ 0 - 4 ]\d|[ 0 - 1 ]?\d?\d)){ 3 }$ |
2、拼接手机号:
1
|
^ 1 [ 3 | 4 | 5 | 8 ][ 0 - 9 ]\d{ 8 }$ |
3、拼接邮箱地址:
1
|
[a - zA - Z0 - 9_ - ] + @[a - zA - Z0 - 9_ - ] + (\.[a - zA - Z0 - 9_ - ] + ) + |