1 """ 2 自省函数: hasattr getattr setattr delattr 3 即反射 4 5 保留方法: 6 __getattr__()只有当没有属性时才调用 7 __delattr__ () 当删除已有属性时调用 8 __setattr__ ()在初始化的时候就会调用(小心会陷入递归) ,直接修改属性字典解决 9 """ 10 import time 11 class DemoClass: 12 def __init__(self,name): 13 self.name = name 14 15 def __setattr__(self, key, value): 16 self.__dict__[key] = value 17 18 if __name__ =="__main__": 19 demo = DemoClass("tom") 20 21 setattr(demo,"age",18) 22 print(demo.__dict__)
通过getattr setattr delattr 来控制了属性的增删改查:
1 class DemoClass: 2 def __init__(self,name): 3 self.name = name 4 5 def __setattr__(self, key, value): 6 if type(value) != str: 7 print("错误!,请赋字符串!") 8 else: 9 self.__dict__[key]=value 10 11 def __delattr__(self, item): 12 print("不允许删除任何属性") 13 14 def __getattr__(self, item): 15 print("你要的{}不存在".format(item)) 16 17 if __name__ =="__main__": 18 # demo = DemoClass(18) 19 demo = DemoClass("tom") 20 21 del demo.name 22 23 demo.age
下面是__getattr__() 和__getattribute__() 的区别:
1 class DemoClass: 2 def __init__(self,name): 3 self.name = name 4 5 def __getattr__(self, item): 6 print("My name is __getattr__") 7 8 def __getattribute__(self, item): 9 print("My name is __getattribute__") 10 11 if __name__ =="__main__": 12 demo = DemoClass("tom") 13 demo.age 14 #输出:My name is __getattribute__ 可见二者并存时,就不需__getattr_工作了 15 #其实是这样的系统默认的getattribute它会抛出一个异常AttributeError 16 #然后,getattr去捕获它, 17 #现在我们重写了系统默认的getattribute,所以getattr就收不到异常,就不工作了 18 19 #总结:系统默认的getattribute 会抛出异常,然后getattr靠接收它来工作 大哥是getattribute 小弟是getattr
文件(模块)也是个对象,所以他们也可以用反射(自省):
注: test.py 和testtest.py 两个文件在同一目录下:
1 #test.py 2 def func01(): 3 pass 4 5 def func02(): 6 pass 7 8 if __name__ =="__main__": 9 pass
1 #testtest.py 2 import test 3 4 print(test) 5 6 print(hasattr(test,"func01")) #模块反射 7 print(hasattr(test,"func")) 8 9 ''' 10 输出: 11 <module 'test' from 'C:\Users\Administrator\Desktop\test\test.py'> 12 True 13 False 14 '''
现在有个问题,如何检测自己模块内部有没有相应的属性呢?
1 import sys 2 3 x = 5 4 def func(): 5 x = 10 #检测的不是它 6 7 8 9 if __name__ == "__main__": 10 11 obj = sys.modules[__name__] #返回自己模块对象 12 print( hasattr(obj,'x')) 13 14 ''' 15 输出: 16 True 17 '''