python中反射是指通过字符串的形式操作对象相关属性。在python中,一切皆对象(只要是对象,都可以通过python的反射机制进行处理)
在做程序开发中,我们常常会遇到这样的需求:需要执行对象里的某个方法,或需要调用对象中的某个变量,但是由于种种原因我们无法确定这个方法或变量是否存在,这是我们需要用一个特殊的方法 或机制要访问和操作这个未知的方法或变量,这中机制就称之为反射。
四个可以实现自省的函数 hasattr() getattr() setattr() delattr()
class Stu:
def __init__(self,name,age,stuid):
self.name=name
self.age=age
self.stuid=stuid
def study(self):
print("good good study,day day up")
#判断对象中是否包含该属性 hasattr(Obj,attr)
s=Stu("史莱克",18,6100116003)
print(hasattr(s,"name"))
print(hasattr(s,"play_game"))
def __init__(self,name,age,stuid):
self.name=name
self.age=age
self.stuid=stuid
def study(self):
print("good good study,day day up")
#判断对象中是否包含该属性 hasattr(Obj,attr)
s=Stu("史莱克",18,6100116003)
print(hasattr(s,"name"))
print(hasattr(s,"play_game"))
运行代码,执行结果为:
True
False
False
#获取属性
print(getattr(s, "name"))
print(getattr(s,"greet"))#getattr(Obj,attr)当只有两个参数时,访问不存在的属性时,会报错
print(getattr(s, "name"))
print(getattr(s,"greet"))#getattr(Obj,attr)当只有两个参数时,访问不存在的属性时,会报错
运行代码,执行结果为:
史莱克
Traceback (most recent call last):
File "F:/python/stuDemo/002.py", line 18, in <module>
print(getattr(s,"greet"))#getattr(Obj,attr)当只有两个参数时,访问不存在的属性时,会报错,将会促发AttributeError
AttributeError: 'Stu' object has no attribute 'greet'
Traceback (most recent call last):
File "F:/python/stuDemo/002.py", line 18, in <module>
print(getattr(s,"greet"))#getattr(Obj,attr)当只有两个参数时,访问不存在的属性时,会报错,将会促发AttributeError
AttributeError: 'Stu' object has no attribute 'greet'
print(getattr(s,"grade",90))#getattr(Obj,attr,default),存在三个参数时,如果属性不存在,就会返回一个默认值,不会报错
运行结果为:
90
也许你会猜想这样一种情况,getattr()存在三个参数时,如果属性不存在,会在该对象的属性字典中添加该属性,并返回属性值,那么我们就来看一下s的属性字典,结果是;
{'name': '史莱克', 'age': 18, 'stuid': 6100116003}
很显然,这证明了,我们的猜想是错误的,说明第三个参数只是我们自己设置的默认返回值
#设置属性setattr(Obj,"key",value)
setattr(s,"name","菠萝吹雪")#修改已经存在的属性
print(s.__dict__)
print(s.__dict__)
运行代码,执行结果为:
{'name': '菠萝吹雪', 'age': 18, 'stuid': 6100116003}
setattr(s,"weight",160)#设置一个不存在的属性,则会在对象的属性字典上添加该属性
print(s.__dict__)
print(s.__dict__)
运行代码,执行结果为:
{'name': '史莱克', 'age': 18, 'stuid': 6100116003, 'weight': 160}
#设置方法属性
def play_game():
print("来啊快活啊")
setattr(s,"play_game",play_game)
print(s.__dict__)
print("来啊快活啊")
setattr(s,"play_game",play_game)
print(s.__dict__)
运行结果为:
{'name': '史莱克', 'age': 18, 'stuid': 6100116003, 'weight': 160, 'play_game': <function play_game at 0x00000000021D2E18>}
#删除属性
delattr(obj,attr)
delattr(s,"play_game")
print(s.__dict__)
print(s.__dict__)
运行结果为:
{'name': '史莱克', 'age': 18, 'stuid': 6100116003, 'weight': 160}delattr(s,"aaaaa")#删除不存在的属性
结果为:
Traceback (most recent call last):
File "F:/python/stuDemo/002.py", line 39, in <module>
delattr(s,"aaaaa")##删除不存在的属性
AttributeError: aaaaa
File "F:/python/stuDemo/002.py", line 39, in <module>
delattr(s,"aaaaa")##删除不存在的属性
AttributeError: aaaaa
__setattr__ __delattr__() __getattr__()
class Foo:
x=1
def __init__(self,y):
self.y=y
def __getattr__(self, item):
print('----> from getattr:你找的属性不存在')
def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value #这就无限递归了,你好好想想
# self.__dict__[key]=value #应该使用它
def __delattr__(self, item):
print('----> from delattr')
# del self.item #无限递归了
self.__dict__.pop(item)
#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)
#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)
#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx