反射的概念是由 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. """ pass
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. """ pass
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‘‘ """ pass
def delattr(x, y): """ Deletes the named attribute from the given object. delattr(x, ‘y‘) is equivalent to ``del x.y‘‘ """ pass
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==
当封装了多个方法,然后需要根据不同条件去调用不同方法的时候,就可以考虑使用反射了,代码量少不是丁点半点
Python - 面向对象编程 - 反射 hasattr、getattr、getattr、delattr
原文:https://www.cnblogs.com/poloyy/p/15259431.html