
众所周知,每一个实例化对象都是有实例化属性或者方法的,之前我们对实例化对象进行属性方法查询、删除或者添加都是直接去通过对象名.属性 去操作的,所以今天我来讲其他方法去操作实例化对象的属性方法,看正文:
什么是反射
反射指的是在程序运行过程中可以“动态(不见棺材不落泪)”的获取对象的信息(属性), 在Python面对对象中,通过字符串的形式去操作对象的属性方法就称之为反射(在Python中一切事物都是可以为对象)
为什么要用反射
实现可插拔机制
- 反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,意味着可以在程序运行过程中动态地绑定接口的实现。
- 这种灵活性使得程序更容易扩展和维护。
| class PluginInterface: |
| def execute(self): |
| pass |
| |
| |
| class PluginA(PluginInterface): |
| def execute(self): |
| print("插件A被启动") |
| |
| |
| class PluginB(PluginInterface): |
| def execute(self): |
| print("插件B被启动") |
| |
| |
| def run_plugin(plugin): |
| plugin.execute() |
| |
| |
| |
| plugin_name = input("请输入插件名字(PluginA or PluginB) :>>>> ") |
| |
| plugin_class = globals().get(plugin_name) |
| |
| |
| if plugin_class and issubclass(plugin_class, PluginInterface): |
| |
| run_plugin(plugin_class()) |
| else: |
| |
| print("Invalid plugin name") |
动态导入模块(基于反射当前模块成员)
- 动态导入模块是指在程序运行时根据字符串的形式导入模块。
- 通过反射,可以动态导入模块的成员,实现更灵活的代码组织和管理。
| import importlib |
| |
| module_name = input("请输入模块名 :>>>> ") |
| method_name = input("请输入方法名 :>>>> ") |
| |
| try: |
| |
| module = importlib.import_module(module_name) |
| |
| method = getattr(module, method_name) |
| |
| method() |
| except ImportError: |
| print("Module not found") |
| except AttributeError: |
| print("Method not found") |
如何使用反射
简介
Python提供了一些内置函数和内置属性,用于实现反射操作,其中常用的有以下几个:
-
hasattr(obj, name)
: 检查对象是否有指定的属性或方法。其中,obj
是要检查的对象,name
是要检查的属性或方法的名称。如果存在该属性或方法,返回True,否则返回False。
-
getattr(obj, name[, default])
: 获取对象的指定属性或方法。其中,obj
是要获取的对象,name
是要获取的属性或方法的名称。如果对象有指定的属性或方法,返回对应的值;如果不存在该属性或方法,如果提供了default
参数,则返回default
值,否则会抛出AttributeError
异常。
-
setattr(obj, name, value)
: 给对象设置指定的属性或方法。其中,obj
是要设置的对象,name
是要设置的属性或方法的名称,value
是要设置的属性或方法的值。
-
delattr(obj, name)
: 删除对象的指定属性或方法。其中,obj
是要删除的对象,name
是要删除的属性或方法的名称。
除了上述函数外,还可以使用内置属性__dict__
来直接访问对象的属性字典,通过操作这个字典,可以实现对对象属性的增删改查。
| class Person: |
| def __init__(self, name, age): |
| self.name = name |
| self.age = age |
| |
| def run(self): |
| print("人可以跑步") |
| |
| |
| person = Person('xaio', 18) |
| |
| |
| print(person.name) |
| |
| |
| |
| print(person.__dict__) |
| |
| |
| |
| print(person.__dict__['name']) |
| |
| |
| |
| print(person.__dir__()) |
| |
| |
| print(dir(person)) |
| |
| |
| 在python中实现反射非常简单,在程序运行过程中,如果我们获取一个不知道存有何种属性的对象,若想操作其内部属性,可以先通过内置函数dir来获取任意一个类或者对象的属性列表,列表中全为字符串格式,接下来就是想办法通过字符串来操作对象的属性了,这就涉及到内置函数hasattr、getattr、setattr、delattr的使用了(Python中一切皆对象,类和对象都可以被这四个函数操作,用法一样)。 |
常用的反射方法使用
1. hasattr() 函数
| 格式: |
| 变量 = hasattr(对象, "对象属性") |
| |
| 作用: |
| 判断对象是否有这个属性以及方法 ,返回布尔类型 |
| |
| 示例: |
| class A(object): |
| def __init__(self,name): |
| self.name=name |
| def fun(self): |
| print(f'我是{self.name}') |
| user=A('Jack') |
| |
| print(hasattr(user,'age')) |
| print(hasattr(user,'name')) |
| print(hasattr(user,'fun')) |
2. getattr() 函数
| 格式: |
| 变量名 = getattr(对象, 对象属性, 默认值) |
| |
| 作用: |
| 获取指定对象的属性以及方法,然后返回这个属性或者方法 |
| |
| 示例: |
| class A(object): |
| def __init__(self,name): |
| self.name=name |
| def fun(self): |
| print(f'我是{self.name}') |
| user=A('Jack') |
| print(user.name) |
| |
| b=getattr(user,'name') |
| a=getattr(user,'age',18) |
| print(user.age) |
| c=getattr(user,'fun') |
| print(b,a) |
| c() |
| print(user.__dict__) |
| |
| |
| |
| |
| 注意看,这里我a=getattr(user,'age',18),其中age不是这个实例化对象的属性,只是我通过这个函数把18这个数字赋值给了c,实际上user和age并没有参与这个赋值,因为user与age一定关系都没有。下面通过__dict__就很明显看出来. |
3. setattr() 函数
| 格式: |
| setattr(对象, "对象属性", 值) |
| |
| 作用: |
| 添加设置对象属性 |
| |
| 示例: |
| |
| class A(object): |
| def __init__(self,name): |
| self.name=name |
| def fun(self): |
| print(f'我是{self.name}') |
| user=A('Jack') |
| |
| user.age=18 |
| print(user.age) |
| |
| setattr(user,'num','137***55***') |
| print(user.name,user.num) |
| print(user.__dict__) |
| |
| |
| |
| |
4. delattr() 函数
| 格式: |
| delattr(对象, 对象属性) |
| |
| 作用: |
| 删除对象属性或者方法 |
| |
| 示例: |
| class A(object): |
| def __init__(self,name,age): |
| self.name=name |
| self.age=age |
| def fun(self): |
| print(f'我是{self.name}') |
| |
| user=A('Jack',18) |
| print(user.__dict__) |
| delattr(user,'age') |
| |
| print(user.__dict__) |
| 可以看出,实例化对象user中的age属性被删除了. |
当然,这四个函数不单单可以在实例化对象使用,Python一切皆对象,所以一个模块,一个函数都是可以去使用的。
通过反射,我们可以在运行时动态地操作对象的属性和方法,这在某些情况下非常有用,例如在配置文件中动态指定需要调用的方法,或者在运行时根据用户的输入来决定调用哪个方法等。但是需要注意的是,反射的使用应该谨慎,因为它破坏了封装性,可能导致代码的可读性和可维护性降低。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏