一文了解Python反射机制(很详细)
https://blog.csdn.net/weixin_40025666/article/details/134456717
https://www.cnblogs.com/mengdie1978/p/17425581.html
一、反射的概念
python的反射机制,核心就是利用字符串去已存在的模块中找到指定的属性或方法,找到方法后自动执行——基于字符串的事件驱动。
二、熟悉面向对象的属性方法
- hasattr(object,'attrName'):判断该对象是否有指定名字的属性或方法,返回值是bool类型
- setattr(object,'attrName',value):给指定的对象添加属性以及属性值
- getattr(object,'attrName'):获取对象指定名称的属性或方法,返回值是str类型
- delattr(object,'attrName'):删除对象指定名称的属性或方法值,无返回值
class Fruit:
# 构造方法
def __init__(self,name,color):
self.name = name
self.color = color
# 类的普通方法
def buy(self,price,num):
print("水果的价格是:",price*num)
"""
hasattr(object,'attrName'):判断该对象是否有指定名字的属性或方法,返回值是bool类型
setattr(object,'attrName',value):给指定的对象添加属性以及属性值
getattr(object,'attrName'):获取对象指定名称的属性或方法,返回值是str类型
delattr(object,'attrName'):删除对象指定名称的属性或方法值,无返回值
"""
apple = Fruit("苹果","红色")
print(hasattr(apple,'name')) # 判断对象是否有该属性或方法
print(hasattr(apple,'buy'))
# 获取对象指定的属性值
print(getattr(apple,'name'))
print(apple.name)
f = getattr(apple,'buy')
f(5,10)
# 设置对象对应的属性
setattr(apple,'weight',100)
# 删除对象对应的属性
delattr(apple,'name')
print(hasattr(apple,'name'))
注:getattr,hasattr,setattr,delattr对模块的修改都在内存中进行,并不会影响文件中真实内容
三、面向对象的反射机制
需求描述:用户通过输入字符串来调用对象的对应方法,通过模拟一个服务器响应用户的请求,设置有注册页、登录页、主页、关于页以及错误页。
class WebSite:
def register(self):
print("欢迎来到注册页面")
def login(self):
print("欢迎来到登录页面")
def home(self):
print("欢迎进入主页")
def about(self):
print("关于我们")
def error(self):
print("404 No Found!")
page = WebSite()
while True:
choose = input("请输入你要进入的页面>>>")
if choose == 'register':
page.register()
elif choose == 'login':
page.login()
elif choose == 'home':
page.home()
elif choose == 'about':
page.about()
else:
page.error()
由于代码段对用户的请求页判断的代码块冗长,并且当新增一个网页时也要实时修改对应的主体代码,维护起来不方便。
class WebSite:
def register(self):
print("欢迎来到注册页面")
def login(self):
print("欢迎来到登录页面")
def home(self):
print("欢迎进入主页")
def about(self):
print("关于我们")
def error(self):
print("404 No Found!")
page = WebSite()
while True:
choose = input("请输入你要进入的页面>>>")
# 反射机制实现上述功能,优化代码结构
if hasattr(page,choose):
f = getattr(page,choose)
else:
page.error()
通过应用面向对象操作属性的方法很好的解决了这个问题,这就是反射机制。Python面向对象中的反射:通过字符串的形式操作对象相关的属性。
四、实例应用
在正式介绍实际web开发中的应用场景之前,先来看看这样的一个模块。
# 模块:importlib
import importlib
res = 'myfile.b'
# 传入字符串路径,调用importlib类,实现 from myfile import b
ret = importlib.import_module(res)
# 该方法最小只能到.py文件名即模块
print(ret)
是的,稍微阅读一下上面的实例代码就可以知道importlib
模块的功能是:即安装字符串式的路径自动导入模块,调用importlib.import_module()
方法,但该方法的最小粒度只能达到.py文件名
即模块。
需求描述:输入多层的模块路径,自动生成对象并调用该类的方法。比如:notify.email.Email,notify包下面有模块email,模块email中包括了Email类,利用该类声明对象,并调用其中的send()方法。
import importlib
#'notify.email.Email'
path_str = input("请输入包-模块-类的字符串路径:")
module_path,class_name = path_str.rsplit('.',maxsplit=1)
# 1 利用字符串导入模块
module = importlib.import_module(module_path) # from notify import email
# 2 利用反射获取类名
cls = getattr(module,class_name) # Email、QQ、Wechat
# 3 生成类的对象
obj = cls()
# 4 直接调用send方法
obj.send()