AI智能
改变未来

Python – 面向对象编程 – 反射 hasattr、getattr、getattr、delattr


什么是反射

反射的概念是由 Smith 在 1982 年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)

Python 面向对象中的反射

  • 通过字符串的形式操作对象的属性
  • Python 中一切皆为对象,所以只要是对象都可以使用反射
  • 比如:实例对象、类对象、本模块、其他模块,因为他们都能通过对象.属性的方式获取、调用

反射中关键的四个函数

  • hasattr
  • getattr
  • setattr
  • delattr

hasattr

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
  • 返回对象是否具有具有给定名称的属性
  • 这是通过调用 getattr(obj,name)并捕获AttributeError来完成的

getattr

def getattr(object, name, default=None):\"\"\"getattr(object, name[, default]) -> valueGet 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\'texist; without it, an exception is raised in that case.\"\"\"pass
  • 获取对象指定名称的属性
  • getattr(x , y)等价写法x.y
  • 当属性不存在,则返回 default 值,如果没有指定 default 就会抛出异常

setattr

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
  • 给指定对象的指定属性设置为值
  • setattr(x,y,v)等价写法x.y = v

delattr

def delattr(x, y):\"\"\"Deletes the named attribute from the given object.delattr(x, \'y\') is equivalent to ``del x.y\'\'\"\"\"pass
  • 从指定对象中删除指定属性
  • delattr(x,y)等价写法del x.y

反射类的成员

class PoloBlog:sum = 0def __init__(self, name):self.name = namedef test(self):print(\"====姓名==== \", self.name)

hasattr

blog = PoloBlog(\"小菠萝\")
# hasattrprint(hasattr(blog, \"name\")) # 实例对象-实例属性print(hasattr(blog, \"sum\")) # 实例对象-类属性print(hasattr(PoloBlog, \"sum\")) # 类对象-类属性print(hasattr(PoloBlog, \"name\")) # 类对象-实例属性# 输出结果TrueTrueTrueFalse

getattr

# getattrprint(getattr(blog, \"name\"))  # 实例对象-实例属性print(getattr(blog, \"sum\"))  # 实例对象-类属性print(getattr(PoloBlog, \"sum\"))  # 类对象-类属性print(getattr(PoloBlog, \"name\", \"默认值\"))  # 类对象-实例属性# 输出结果小菠萝00默认值

setattr

# 设置一个新的实例属性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

# delattrdelattr(blog, \"age\")delattr(blog, \"printNameAge\")print(blog.__dict__)# 输出结果{\'name\': \'小菠萝\'}

反射本模块的成员

除了可以检测类中有没有某个属性、方法,还可以用来检测某个模块下有没有方法、类、变量

sums = 0def test1():print(\"test\")class A():passthis_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\'>TrueTrueTrue

反射其他模块的成员

输出结果

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 respdef post(self, url):resp = self.req.post(url)print(\"==post==\")return respdef 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==

总结

当封装了多个方法,然后需要根据不同条件去调用不同方法的时候,就可以考虑使用反射了,代码量少不是丁点半点

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Python – 面向对象编程 – 反射 hasattr、getattr、getattr、delattr