
反射的概念是由 Smith 在 1982 年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)
对象.属性
def hasattr(*args, **kwargs):
"""
Return whether the object has an attribute with the given name.
This is done by calling getattr(obj, name) and catching AttributeError.
"""
passgetattr(obj,name)
def getattr(object, name, default=None):
"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
passgetattr(x , y)
def setattr(x, y, v):
"""
Sets the named attribute on the given object to the specified value.
setattr(x, 'y', v) is equivalent to ``x.y = v''
"""
passsetattr(x,y,v)
def delattr(x, y):
"""
Deletes the named attribute from the given object.
delattr(x, 'y') is equivalent to ``del x.y''
"""
passdelattr(x,y)
class PoloBlog:
sum = 0
def __init__(self, name):
self.name = name
def test(self):
print("====姓名==== ", self.name)blog = PoloBlog("小菠萝")
# hasattr
print(hasattr(blog, "name")) # 实例对象-实例属性
print(hasattr(blog, "sum")) # 实例对象-类属性
print(hasattr(PoloBlog, "sum")) # 类对象-类属性
print(hasattr(PoloBlog, "name")) # 类对象-实例属性
# 输出结果
True
True
True
False# getattr
print(getattr(blog, "name")) # 实例对象-实例属性
print(getattr(blog, "sum")) # 实例对象-类属性
print(getattr(PoloBlog, "sum")) # 类对象-类属性
print(getattr(PoloBlog, "name", "默认值")) # 类对象-实例属性
# 输出结果
小菠萝
0
0
默认值# 设置一个新的实例属性
setattr(blog, "age", 24)
# 设置一个新的实例方法
setattr(blog, "printNameAge", lambda self: f"姓名:{self.name} 年龄:{self.age}")
print(blog.__dict__)
print(blog.printNameAge(blog))
# 输出结果
{'name': '小菠萝', 'age': 24, 'printNameAge': <function <lambda> at 0x10391a1f0>}
姓名:小菠萝 年龄:24# delattr
delattr(blog, "age")
delattr(blog, "printNameAge")
print(blog.__dict__)
# 输出结果
{'name': '小菠萝'}除了可以检测类中有没有某个属性、方法,还可以用来检测某个模块下有没有方法、类、变量
sums = 0
def test1():
print("test")
class A():
pass
this_module = sys.modules[__name__]
print(__name__)
print(this_module)
print(hasattr(this_module, "sums")) # 变量
print(hasattr(this_module, "test1")) # 方法
print(hasattr(this_module, "A")) # 类
# 输出结果
__main__
<module '__main__' from '/Users/polo/Documents/pylearn/第四章:面向对象/22_反射.py'>
True
True
True
True
反射22222
小菠萝 fanshe 是另一个模块
class Web:
def login(self):
print('欢迎来到登录页面')
def register(self):
print('欢迎来到注册页面')
def save(self):
print('欢迎来到存储页面')
while True:
obj = Web()
choose = input(">>>").strip()
if choose == 'login':
obj.login()
elif choose == 'register':
obj.register()
elif choose == 'save':
obj.save()class Web:
def login(self):
print('欢迎来到登录页面')
def register(self):
print('欢迎来到注册页面')
def save(self):
print('欢迎来到存储页面')
while True:
obj = Web()
choose = input(">>>").strip()
# 判断对象是否有对应的方法
if hasattr(obj, choose):
# 获取对应的方法
f = getattr(obj, choose)
# 执行方法
f()在做接口自动化测试的时候,我们一般都会封装 BaseRequest 类来进行复用,类里面会封装不同请求方法
class BaseRequest:
req = requests.Session()
def get(self, url):
resp = self.req.get(url)
print("==get==")
return resp
def post(self, url):
resp = self.req.post(url)
print("==post==")
return resp
def put(self, url):
resp = self.req.put(url)
print("==put==")
return resp
# 不使用反射的方法
def main(self, method, url):
if method == "get":
self.get(url)
elif method == "post":
self.post(url)
elif method == "put":
self.put(url) # 使用反射的方法
def main_attr(self, method, url):
if hasattr(self, method):
func = getattr(self, method)
func(url)request = BaseRequest()
# 不使用反射
request.main("get", "http://www.baidu.com")
request.main("post", "http://www.baidu.com")
request.main("put", "http://www.baidu.com")
# 使用反射
request.main_attr("get", "http://www.baidu.com")
request.main_attr("post", "http://www.baidu.com")
request.main_attr("put", "http://www.baidu.com")
# 输出结果
==get==
==post==
==put==
==get==
==post==
==put==当封装了多个方法,然后需要根据不同条件去调用不同方法的时候,就可以考虑使用反射了,代码量少不是丁点半点