什么是反射(Reflection)?

一句话大白话:

反射 = 用字符串的名字,去操作对象的属性和方法。

正常写代码:

obj.name
obj.say()

反射写代码:

getattr(obj, "name")
getattr(obj, "say")()

再直白一点:

程序运行时,不知道对象有什么属性、方法,但我拿到一个字符串名字,就能动态获取、修改、调用它。

这就叫反射。

为什么要叫 “反射”?

对象就像站在你面前的人。你不用直接碰他,而是通过 “名字字符串” 这个镜子,照到他内部的属性和方法,然后操作。

镜子 = 字符串照到内部 = 获取 / 修改 / 调用这就是反射。


三、反射三剑客(核心!必须背下来)

Python 反射只有 3 个内置函数,全部操作对象:

1. hasattr → 有没有?

判断对象是否包含某个属性 / 方法返回 True / False

hasattr(obj, "属性名字符串")

例子:

class User:
    name = "张三"

u = User()
print(hasattr(u, "name"))  # True
print(hasattr(u, "age"))   # False

2. getattr → 拿值!

通过字符串名字,获取属性的值 或 获取方法

getattr(obj, "属性名")
getattr(obj, "属性名", 默认值)  # 没有就返回默认值,不报错

例子:

name = getattr(u, "name")  # 获取 name 属性
print(name)  # 张三

age = getattr(u, "age", 0)  # 没有 age,返回 0

调用方法:

func = getattr(u, "say")
func()  # 调用方法

3. setattr → 赋值!

通过字符串名字,设置 / 修改属性的值

setattr(obj, "属性名字符串", 新值)

例子:

setattr(u, "name", "李四")
print(u.name)  # 李四

四、三剑客一起用(最经典写法)

# 1. 先判断有没有
if hasattr(obj, "target"):
    # 2. 有就拿出来
    val = getattr(obj, "target")
    # 3. 想改就改
    setattr(obj, "target", val + 1)

五、反射到底有什么用?(你必须知道)

1. 动态处理,代码更灵活

不知道属性名是什么,从配置、接口、用户输入里拿到字符串,照样能操作。

2. 框架底层必用(asyncio、Django、Flask、爬虫、ORM 全靠它)

比如:

  • 根据路由字符串调用对应函数
  • 事件循环根据事件名调用回调
  • 消息处理根据类型调用处理方法

3. 代码不报错,更健壮

不用 obj.xxx 怕不存在报错,用 getattr(obj, "xxx", 默认) 安全无比。


六、超级简单示例(一看就懂)

class Student:
    def __init__(self):
        self.name = "小明"
        self.age = 18

    def study(self):
        print("学习中")

s = Student()

# 反射开始!
# 1. 判断
print(hasattr(s, "name"))  # True

# 2. 获取
print(getattr(s, "name"))  # 小明

# 3. 修改
setattr(s, "age", 20)
print(s.age)  # 20

# 4. 调用方法
func = getattr(s, "study")
func()  # 学习中

七、终极总结(背这 4 行就够)

  1. 反射 = 用字符串操作对象属性 / 方法
  2. hasattr:判断有没有
  3. getattr:获取值 / 方法
  4. setattr:设置值
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐