python3 反射
hasattr(obj, str) 判断obj对象中是否有str成员
getattr(obj, str) 从obj对象中获取str成员
setattr(obj, str, value) 把obj对象中的str设置为value
delattr(obj, str) 从obj对象中删除str成员
以上方法都是在内存中执行的,不会影响源代码
先看下hasattr和getattr的使用
# master.py name = "lily" def func1(): print("我是func1") def func2(): print("我是func2") def func3(): print("我是func3") class Person: pass
# test反射.py from types import FunctionType import master while 1: inp = input("请输入你要执行的方法:").strip() if hasattr(master, inp): fn = getattr(master, inp) if callable(fn): # 同 if isinstance(fn, FunctionType): fn() else: print(fn) else: print("输入的变量名不存在")
执行test反射.py的结果:
请输入你要执行的方法:name lily 请输入你要执行的方法:func1 我是func1 请输入你要执行的方法:func2 我是func2 请输入你要执行的方法:aa 输入的变量名不存在 请输入你要执行的方法:Person <class 'master.Person'> 请输入你要执行的方法:
接下来看下setattr的使用(只是在内存中修改,对源代码无影响)
# setattr实例.py import master fn = lambda: print("我是修改后的func1") # 无参数无返回值的函数 # def fn(): # 同fn = lambda: print("我是修改后的func1") # print("我是修改后的func1") master.func1() setattr(master, "func1", fn) master.func1()
执行setattr实例.py的结果:
我是func1
我是修改后的func1
delattr的使用(只是在内存中删除,对源代码无影响)
import master print(master.func1) delattr(master, "func1") print(master.func1) # AttributeError: module 'master' has no attribute 'func1'
执行结果:
Traceback (most recent call last): File "G:/python28/code/python-28/day07/反射/delattr的操作.py", line 6, in <module> print(master.func1) AttributeError: module 'master' has no attribute 'func1' <function func1 at 0x00000000029779D8>
一定要注意反射在类中的使用,不能建议使用getattr(类名, 方法名)
class Person: def __init__(self, name, age): self.name = name self.age = age def func(self): print(f"我是func 我的名字是{self.name}") p = Person("lily", 18) f1 = getattr(p, "func") f1() f2 = getattr(Person, "func") # f2() # 报错TypeError: func() missing 1 required positional argument: 'self' f2(p)
执行结果:
我是func 我的名字是lily
我是func 我的名字是lily
总结:
fn = getattr(obj, str1) 相当于fn = obj.str1
fn() 相当于obj.str1()
f1 = getattr(p, "func") 相当于f1 = p.func
f1() 相当于p.func() 因为 func是实例方法,所以对象调用实例方法是正常的。如果这里看着费劲或者看不懂,请先 https://www.cnblogs.com/lilyxiaoyy/p/11988523.html
f2 = getattr(Person, "func") 相当于 f2 = Person.func
f2() 相当于Pereson.func() 这里肯定是报错的,因为实例方法的一个参数默认是对象self
f2(p) 相当于Person.func(p) 手动把对象p传递给实例方法的第一个参数,不推荐使用类名调用实例方法。
反射在类中的使用
# 反射在类中的使用.py class Person: def __init__(self, name, age): self.name = name self.age = age def func(self): print(f"我是func 我的名字是{self.name}") p = Person("lily", 18) if hasattr(p, "func"): # attribute 判断p对象中是否有func属性 fn = getattr(p, "func") # 从p对象中获取func属性 if callable(fn): # 判断是否可以被调用 + () fn() # delattr(p, "name") # 删除p对象中的name属性 # print(p.name) p2 = Person("lucy", 16) print(p2.name) setattr(p, "address", "北京市八大胡同") # 给p对象设置address属性,值为北京市八大胡同 print(p.address) # 北京市八大胡同 setattr(p, "func2", lambda: print("我是func2")) p.func2()
执行结果:
我是func 我的名字是lily
lucy
北京市八大胡同
我是func2