Python之反射,正则
本节主要内容:
一. 反射:
getattr
hasattr
setattr
defattr
二. 补充模块中特殊的变量
三. 正则表达式
re模块
(一)反射:
- hasattr(object, name) 检查
- getattr(object, name) 寻找
- setattr(object, name, value) 设置
- delattr(object, name) 删除
说明:判断对象object是否包含名为name的特性(hasattr是通过调用getattr(ojbect, name)是否抛出异常来实现的)。
参数object:对象。
参数name:特性名称。
#利用字符串的形式去对象(模块)中操作(寻找,检查,设置,删除)成员。
例子:
1 #模拟网站不同url访问不同页面 2 3 ##commons.py 4 5 def login(): 6 print("登陆页面") 7 8 def logout(): 9 print("退出页面") 10 11 def home(): 12 print("主页面") 13 14 15 ##index 16 17 import commons 18 19 #利用字符串的形式去对象(模块)中操作(寻找)成员。 20 def run(): 21 inp = input("请输入要访问的页面:") 22 23 if hasattr(commons,inp): 24 func = getattr(commons,inp) 25 func() 26 else: 27 print("404") 28 29 if __name__ == '__main__': 30 run() 31 32 #输出: 33 34 请输入要访问的页面:login 35 登陆页面 36 请输入要访问的页面:home 37 主页面 38 请输入要访问的页面:fsdfsf 39 404
##模块实现反射
1 ##index.py 2 3 def run(): 4 #account/login 5 inp = input("请输入要访问的url:") 6 7 m, f = inp.split('/') #m为模块,f模块中函数,中间用/分隔 8 obj = __import__(m) 9 if hasattr(obj, f): 10 func = getattr(obj, f) 11 func() 12 else: 13 print("404") 14 if __name__ == '__main__': 15 run() 16 17 ##account.py 18 19 def login(): 20 print("登陆页面") 21 22 def logout(): 23 print("退出页面") 24 25 ##manager.py 26 27 def order(): 28 print("订单页面") 29 30 #输出: 31 32 请输入要访问的url:account/login 33 登陆页面 34 请输入要访问的url:manager/order 35 订单页面 36 请输入要访问的url:account/sfdsdf 37 404
##模块多层目录时,可使用fromlist = True
1 ##lib/test/account.py #多层级目录 2 3 m, f = inp.split('/') 4 obj = __import__("lib." + m ,fromlist = True) 5 #目录加.(点),后+模块,fromlist = True
( 二) 补充模块中特殊的变量
__doc__: 显示注释信息
__cached__: pyc文件路径
__file__: 当前py文件所在路径
os.path.dirname: 找到某个文件的上级目录
os.path.abspath: 获取某个文件的绝对路径
1 import os,sys 2 3 #sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 4 5 print(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 6 7 #输出: 8 9 D:\python程序\s13\day6\模块 #输出file绝对路径的上级目录的上级目录
#注: 一般可执行文件都需要加入。
__package__: 查找模块在哪个目录,当前目录使用返回None
__name__:
如果我们是直接执行某个.py文件的时候,该文件中那么”__name__ == '__main__'“是True,但是我们如果从另外一个.py文件通过import导入该文件的时候,这时__name__的值就是我们这个py文件的名字而不是__main__。
这个功能还有一个用处:调试代码的时候,在”if __name__ == '__main__'“中加入一些我们的调试代码,我们可以让外部模块调用的时候不执行我们的调试代码,但是如果我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!
hashlib : 用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法.
1 import hashlib 2 3 obj = hashlib.md5(bytes('3454abdFdf', encoding='utf-8')) 4 obj.update(bytes('admin',encoding='utf-8')) 5 print(obj.hexdigest())
三. 正则表达式(re)
正则表达式(re)是由一些字符和特殊符号组成的字符串,通过某个模式匹配到有相似特征的字符串,可以是单个也可以是多个。
正则表达式使用的特殊符合和字符
re模块:
最常用的几个方法:
compile(pattern,flages=0): 对正则表达式模式pattern进行编译,flags为可选标志符,并返回一个regex对象
match(pattern,string, flages=0) : 尝试用正则表达式模式pattern匹配字符串string,flages可选标志符,如果匹配成功返回匹配对象,否则返回None.
search(pattern,string, flages=0) : 在字符串string中查找正则表达式模式pattern的第一次出现,匹配成功,返回匹配对象,否则为None。
findall(pattern,string[,flages]): 在字符串string中查找正则表达式模式pattern的所有(非重复)出现: 返回一个匹配对象的列表。
finditer(pattern,string[,flages]): 和findall相同,但返回的是一个迭代器而不是一个列表,对于每个匹配,该迭代器返回一个匹配对象。
split(pattern,string, max=0): 根据正则表达式pattern中的分隔符把字符string分割为一个列表,返回成功匹配的列表,最多分割max次(默认分割所有匹配过的地方)
sub(pattern, repl, string, max=0) : 把字符串string中所有匹配正则表达式pattern的地方替换成字符串repl,如果max的值没有给出,默认对所有匹配到的地方进行替换。与sub相同的subn()则会返回一个表示替换次数的数值。
group(num=0) : 返回所有匹配对象(或指定编号是num的子组)
groups() : 返回一个包含全部匹配的子组的元组(如果没有成功匹配,则返回一个空的元组)
###match(): 匹配字符串
1 #####match##### 2 3 import re 4 5 m = re.match('foo','foo') #模式匹配字符串 6 if m is not None: #如果不为None,则成功显示foo 7 print(m.group()) 8 print(m) #返回一个匹配对象的实例。 9 10 #虽然定义字符串长,但是匹配是从开头匹配,成功则返回。否则报错。 11 m1 = re.match('foo','food on the table').group() 12 print(m1) 13 14 #输出: 15 foo 16 <_sre.SRE_Match object; span=(0, 3), match='foo'> 17 18 foo
###search() : 在一个字符串中查找一个模式
1 #####search##### 2 3 m = re.match('foo','seafood').group()#匹配不到会抛出异常 4 print(m) 5 6 m = re.search('foo', 'seafood').group()#可以匹配任意位置 7 print(m) 8 9 输出: 10 AttributeError: 'NoneType' object has no attribute 'group' 11 12 foo
###findall():找到每个出现的匹配部分
1 #####findall##### 2 3 print(re.findall('car','car')) 4 print(re.findall('car','mycar')) 5 print(re.findall('car','carry the barcardi to the car')) 6 7 #输出: 8 9 ['car'] 10 ['car'] 11 ['car', 'car', 'car']
注意 :
findall()与search()相同的是二者都可在任意位置执行字符串搜索,findall()与search(),match()不同之处,findall()总返回一个列表,没有匹配则返回空列表,匹配到,返回所有匹配部分(从左到右)。
###sub()[subn()]: 进行搜索和替换
1 #####sub,subn##### 2 3 print(re.sub('hongfei','zhaohongfei', 'My name is hongfei')) 4 #匹配到hongfei并替换为zhaohongfei 5 6 print(re.subn('hongfei','zhaohongfei', 'My name is hongfei')) 7 #与sub相同,但是返回一个元组,并记录匹配次数 8 9 print(re.sub('[abc]','ABC','gtdacf'))#多个元素匹配 10 11 print(re.subn('[abc]','ABC','gtdacf')) 12 13 #输出: 14 15 My name is zhaohongfei 16 17 ('My name is zhaohongfei', 1) 18 19 gtdABCABCf 20 ('gtdABCABCf', 2)
###split(): 分割
1 #####split()##### 2 3 print(re.split(':','zhao:hong:fei')) #以分号分割字符串 4 print(re.split(':','zhao:hongfei')) 5 6 #输出: 7 8 ['zhao', 'hong', 'fei'] 9 ['zhao', 'hongfei']
###group(), groups()
1 #####group, groups##### 2 3 import re 4 5 ###group 6 a = "123abc456" 7 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0)) #123abc456,返回整体 8 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1)) #123 9 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2)) #abc 10 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3)) #456 11 12 ###gorups #都是返回整体 13 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).groups(0)) 14 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).groups(1)) 15 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).groups(2)) 16 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).groups(3)) 17 18 #输出: 19 20 123abc456 21 123 22 abc 23 456 24 25 ('123', 'abc', '456') #由此可以看到groups为返回匹配的整体 26 ('123', 'abc', '456') 27 ('123', 'abc', '456') 28 ('123', 'abc', '456')
1. 正则表达式中的三组括号把匹配结果分成三组
- group() 同group(0)就是匹配正则表达式整体结果
- group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。
2. 没有匹配成功的,re.search()返回None
3. groups为返回匹配到的整体的一个元组。
以上为所学内容总结,后续会继续完善,谢谢!