面向对象之反射
目录
一、面向对象之反射
0.反射的含义
反射:自省的一种方式,利用字符串操作对象的数据和方法
用户所传递的信息都是字符串类型,所以利用反射可以与用户进行交互
1. hasattr:判断一个方法是否存在与这个类中 2. getattr:根据字符串去获取obj对象里的对应的方法的内存地址,加"()"括号即可执行 3. setattr:通过setattr将外部的一个函数绑定到实例中 4. delattr:删除一个实例或者类中的方法
1.hasattr(object,name)
判断对象是否含有某个字符串对应的属性名或者方法名
2.getattr()
根据字符串获取对象对应的属性名(值)或方法名
如果没有名字则会报错,所以常常和hasattr搭配使用
(1)案例中体会反射在与用户交互中的便捷与突破性
class C1: name = 'duoduo' def choice_name(self): print('你是谁') # 产生C1的对象 obj = C1()
1)判断某个名字是否可以被使用(存在)
# 当我们想判断对象obj中是否存在某个名字,却不想让其报错的时候可以考虑到用异常处理 try: obj.aaa except AttributeError: print('不存在这个名字')
2)判断用户随意指定的名字对象是否可以使用(存在)
# 在异常处理的基础上,增加与用户交互的功能 target_name = input('请输入名字:').strip() try: obj.target_name except AttributeError: print('不存在这个名字')
3)反射的功能则可以用字符串来操作对象的数据和方法
# 反射:利用字符串操作对象的数据和方法 print(hasattr(obj, 'name')) # True print(getattr(obj, 'name')) # duoduo print(getattr(obj, 'choice_name')) # <bound method C1.choice_name of <__main__.C1 object at 0x103191f10>>
4)综合起来利用反射来和用户进行交互
# 利用反射的方法,来动态获取想判断的名字 class C1: name = 'duoduo' def choice_name(self): print('你是谁') obj = C1() while True: target_name = input('请输入名字:').strip() if hasattr(obj,target_name): print('有名字') # 获取该名字对应的数据(值 函数地址) data_or_func = getattr(obj,target_name) if callable(data_or_func): print('这名字是某个方法') else: print('这名字对应的是值') print(data_or_func) else: print('没有该名字')v
3.setattr(object, name, value)
根据字符串给对象设置或者修改数据
obj1 = C1() setattr(obj1, 'age', 18) print(obj1.__dict__) # {'age': 18}
4.delattr(object, name)
根据字符串删除对象里面的名字
class C1: name = 'duoduo' def choice_name(self): print('你是谁') obj1 = C1() # 类C1产生了一个对象obj1 1.hasattr()判断名字是否存在 res = hasattr(obj1, 'choice_name') print(res) # True 2.setattr() 为obj1添加属性或者方法 setattr(obj1, 'age', 18) # 为obj1增加一个属性为 age = 18 print(obj1.__dict__) # {'age': 18} 查看后在obj1中成功增加来 age = 18的属性 setattr(obj1, 'age', lambda a: a + 1) print(obj1.__dict__) # {'age': <function <lambda> at 0x10242a280>} 3.delattr() 删除属性或者方法 delattr(obj1, 'age') print(obj1.__dict__) # {} 空集合代表,该对象没有自己独有的功能或者属性
二、反射实战案例
1.使用反射的场景:
只要需求中出现了关键字:对象...字符串...
2.案例
(1)模拟终端
class WinCmd: def tasklist(self): print(""" 1.学习编程 2.学习python 3.学习英语 """) def ipconfig(self): print(""" 地址:127.0.0.1 地址:上海浦东新区 """) def get(self, target_file): print('获取文件', target_file) def put(self, target_file): print('上传文件', target_file) def server_run(self): print("欢迎进入简易版本cmd终端".center(50, '=')) while True: target_cmd = input('请输入您的指令>>>:') res = target_cmd.split(' ') # 因为在终端中输入命令常常有空格 if len(res) == 1: if hasattr(self, res[0]): getattr(self, res[0])() # 存在该命令则执行 else: print(f'{res[0]}不是内部或者外部命令') # 如果传入了参数,则执行该命令并传入参数 elif len(res) == 2: if hasattr(self, res[0]): getattr(self, res[0])(res[1]) else: print(f'{res[0]}不是内部或者外部命令') obj = WinCmd() # 产生类WinCmd的对象 obj.server_run() # 调用obj的方法server_run
(2)一切皆对象
利用反射保留某个py文件中所有的大写变量名以及对应到数据值
- settings.py文件中
NAME = 'duoduo' AGE = 13 desc = '吃饭天' info = '没到点' def name(): print('name') class Person: name = 'duoduo'
执行文件中
查看文件中的名字也可以用dir()
方法,列举对象可以使用的名字
查看文件中的名字也可以用
__dict__
方法,print(settings.__dict__)
但是文件中的名字会有很多,所以如果class类更适合用
__dict__
方法
(1)传统方法
import settings print(dir(settings)) # dir是列举对象可以使用的名字 # ['AGE', 'NAME', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'desc', 'info'] 1.方式一:for循环 + 判断 # 构造一个空字典,用来存放我们想要的名字 useful_dict = {} for name in dir(settings): if name.isupper(): # 保留大写 useful_dict[name] = getattr(settings,name) print(useful_dict) # {'AGE': 13, 'NAME': 'duoduo'} 2.方式二:生成式 useful_dict = {name: getattr(settings, name) for name in dir(settings) if name.isupper()} print(useful_dict) # {'AGE': 13, 'NAME': 'duoduo'}
(2)利于反射动态获取
# 用反射判断settings.py文件中是否有某个名字 while True: target_name = input('请输入您想判断的某个名字:').strip() if hasattr(settings, target_name): print(getattr(settings, target_name)) """ 如果存在该名字则返回值, 是方法则返回方法的内存地址<function name at 0x1004a7d30>, 如果是类名则返回类的名字<class 'settings.Person'> """ else: print('该模块文件中没有该名字')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY