什么是反射
反射是一个很重要的概念,它可以把字符串映射到实例的变量或者实例的方法然后可以去执行调用、修改等操作。它有四个重要的方法:
- getattr 获取指定字符串名称的对象属性
- setattr 为对象设置一个对象
- hasattr 判断对象是否有对应的对象(字符串)
- delattr 删除指定属性
但是要注意不能是私有的,如果你的变量是以“_”开头,那将无法获取。
简单来说 getattr就是能吧原先原先对象点属性,或者对象点方法换成对象点任意字符串的操作。
反射的使用场景
反射常常用在动态加载模块的场景中。
#!/usr/bin/env python # -*- coding: utf-8 -*- # Author: rex.cheny # E-mail: rex.cheny@outlook.com class TestObj(object): def __init__(self, name, age): self.name = name self.age = age def displayName(self): print("displayName方法执行,打印姓名:", self.name) def AAA(self): print("I am AAA.") def main(): to = TestObj("Tom", 23) # 查看 to 实例里面是否有 name 这个属性 if hasattr(to, "name"): print("实例 to 中有 name 属性。") print(getattr(to, "name")) else: print("实例 to 中没有 name 属性。") if hasattr(to, "displayName"): print("实例 to 中有 displayName 属性。") getattr(to, "displayName")() else: print("实例 to 中没有 displayName 属性。") if hasattr(to, "AAA"): print("实例 to 中有 AAA 属性。") getattr(to, "AAA")() else: print("实例 to 中没有 AAA 属性,将会设置。") setattr(to, "AAA", AAA) # 参数:实例、方法名称、具体方法 相当于 to.AAA = AAA 第一个AAA是函数在实例中的名称, 第二个AAA是把哪个函数放进去,两者只是恰好这里名称一样 # to.AAA(to) # 这里一定要主动传递一个实例进去,因为它不会自动装配self getattr(to, "AAA")(to) if __name__ == '__main__': main()
AAA是动态装载到实例里面去的。
再举一个小栗子
#!/usr/bin/env python # -*- coding: utf-8 -*- # Author: rex.cheny # E-mail: rex.cheny@outlook.com class TestObj(object): def __init__(self, name): self.name = name def displayname(self): print(self.name) def main(): to = TestObj(name="Tom") cmd = input("输入:") if hasattr(to, cmd): pass else: setattr(to, cmd, displayname) func = getattr(to, cmd) func(to) if __name__ == '__main__': main()
根据用户输入来调用函数(这个函数肯定要提前的真实存在)。我这里无论我输入什么都可以执行上面的displayname方法。