Python中的反射
Python 中的反射(Reflection)详解
反射是指程序在运行时动态访问、检测和修改其自身状态(如属性、方法、类信息)的能力。Python 通过内置函数和特殊属性提供了强大的反射支持,核心功能包括 动态访问对象成员、检查类型、修改属性和调用方法。
一、反射的核心功能
1. 动态访问属性
(1) getattr(object, name[, default])
获取对象的属性或方法,若不存在可返回默认值或抛出 AttributeError
。
class Student:def __init__(self, name):self.name = namestu = Student("Alice")
print(getattr(stu, "name")) # 输出: Alice
print(getattr(stu, "age", 18)) # 属性不存在,返回默认值 18
(2) hasattr(object, name)
检查对象是否包含指定属性或方法。
if hasattr(stu, "name"):print("存在属性 name") # 输出: 存在属性 name
(3) setattr(object, name, value)
动态设置或修改对象的属性。
setattr(stu, "age", 20) # 等价于 stu.age = 20
print(stu.age) # 输出: 20
(4) delattr(object, name)
删除对象的属性。
delattr(stu, "age") # 等价于 del stu.age
print(hasattr(stu, "age")) # False
2. 动态调用方法
通过 getattr()
获取方法后调用:
class Calculator:def add(self, a, b):return a + bcalc = Calculator()
method = getattr(calc, "add")
print(method(3, 5)) # 输出: 8
3. 反射与模块
动态导入模块并访问其内容:
module_name = "math"
math_module = __import__(module_name) # 动态导入
sqrt_func = getattr(math_module, "sqrt")
print(sqrt_func(9)) # 输出: 3.0
二、反射的应用场景
1. 插件系统
动态加载和执行插件:
# 假设插件模块名为 "plugin_hello"
plugin_name = "plugin_hello"
plugin = __import__(f"plugins.{plugin_name}", fromlist=["run"])
plugin.run() # 调用插件的 run() 方法
2. 配置文件驱动行为
根据配置调用不同方法:
config = {"action": "save", "target": "data"}
obj = Database()if hasattr(obj, config["action"]):method = getattr(obj, config["action"])method(config["target"])
3. ORM 框架
动态映射数据库字段到类属性:
class User:def __init__(self, **kwargs):for key, value in kwargs.items():setattr(self, key, value)user = User(name="Alice", age=25)
print(user.name) # Alice
三、反射的底层原理
Python 对象的属性存储在 __dict__
字典中,反射操作本质是对 __dict__
的访问:
class Demo:passdemo = Demo()
demo.__dict__["x"] = 10 # 等价于 demo.x = 10
print(demo.x) # 输出: 10
四、反射的安全注意事项
- 避免动态执行用户输入:
user_input = "os.system('rm -rf /')" # 危险! # 不要直接 eval(user_input) 或 getattr(os, "system")("rm -rf /")
- 限制反射范围:使用
hasattr()
检查属性是否存在后再操作。
五、总结
功能 | 方法 | 用途 |
---|---|---|
检查属性/方法 | hasattr(obj, "name") | 安全访问前校验 |
获取属性/方法 | getattr(obj, "name") | 动态调用方法或读取属性 |
设置属性 | setattr(obj, "name", value) | 动态修改或添加属性 |
删除属性 | delattr(obj, "name") | 动态删除属性 |
动态导入模块 | __import__(module_name) | 运行时加载模块 |
核心价值:
反射使代码更灵活,但需谨慎使用以确保安全性和可维护性。