一,反射
1:反射:自省也称为反射,这个性质展示了某个对象是如何在运行期间取得自身的信息
2:如果传递一个对象给你,你应该可以查出该对象具有的能力,在Python中如果不具有自省能力,那么dir和type内建立的函数就无法正常的工作
3:反射指的是程序可以访问,检测,修改本身状态或行为的一种能力
## 四个可以实现自省的函数(适用于类和对象)
# 1:检测字符串name对应的属性或方法在不在对象Object中
hasattr(Object,name)
class Java: def __init__(self,name,size): self.name = name self.size = size def test_java(self): pass j = Java("new_java",10) print(hasattr(j,"name")) # True 实际上找的是对象j能不能调用到属性name print(hasattr(j,"test_java")) # True 实际上找的是对象j能不能调用到属性test_java
# 2:找到属性对应的值或找到函数对应的地址,如果不错在则报错
getattr(Object,name,default=None)
class Java: def __init__(self,name,size): self.name = name self.size = size def test_java(self): pass j = Java("new_java",10) print(getattr(j,"name")) # new_java print(getattr(j,"test_java")) # <bound method Java.test_java of <__main__.Java object at 0x0000020152999470>> print(getattr(j,"hello","不存在该参数")) # 不存在该参数 当不存在时,则打印该参数
# 3:给对象添加一个属性,x:对象名,y:所要添加的属性名,v:属性的值
setattr(x,y,v)
class Java: def __init__(self,name,size): self.name = name self.size = size def test_java(self): pass j = Java("new_java",10) ## 添加数据属性 setattr(j,"starttime","2018.1.1") # 给对象添加属性starttime print(j.__dict__) # {'name': 'new_java', 'size': 10, 'starttime': '2018.1.1'} ## 添加函数属性 setattr(j,"func",lambda x:x+1) print(j.__dict__) # {'name': 'new_java', 'size': 10, 'starttime': '2018.1.1', 'func': <function <lambda> at 0x000002561C75B950>}
# 4:删掉对应的属性
delattr(x,y)
class Java: def __init__(self,name,size): self.name = name self.size = size def test_java(self): pass j = Java("new_java",10) delattr(j,"name") print(j.__dict__) # {'size': 10}
## 补充
class Test: def __init__(self,name): self.name = name def func(): pass @staticmethod def func1(): return "func1" print( getattr(Test,"name") ) print( getattr(Test,"func") )
# 5:双下划线开头的attr __getattr__ __setattr__ __delattr__
这戏额内置方法是给类实例化出来的对象使用的,类不能直接调用
# __getattr__
# 当一个对象调用一个不存在的属性时,__getattr__会执行 class Test: def __init__(self,name): self.name = name def __getattr__(self, item): print("执行了__getattr__方法,%s不存在" %item) t = Test("henry") t.x # 执行了__getattr__方法,x不存在
# __delattr__
# 当删除对象自己的一个属性时,会调用 __delattr__ # 当删除非对象的属性时,也会执行 __delattr__ # 当在类中没有写入__delattr__方法,当执行del t.name时,会直接将该属性删除
# __delattr__用法1 class Test: def __init__(self,name): self.name = name def __delattr__(self, item): print("开始删除属性%s" %item) # 开始删除属性name self.__dict__.pop(item) # 删除itme t = Test("henry") del t.name print(t.__dict__) # {} 为空,name已经被删除
# __delattr__用法2 class Test: def __init__(self,name): self.name = name def __delattr__(self, item): print("不允许删除属性%s" %item) # 不允许删除属性name t = Test("henry") del t.name print(t.__dict__) # {'name': 'henry'}
# __setattr__
# 当对象设置(新增,修改)属性时,setattr会被调用 class Test: def __init__(self,name): self.name = name def __setattr__(self, key, value): print("__setattr__被调用") t = Test("henry") t.username = "heihei" # 输出 # __setattr__被调用 在实例化出对象的时调用一遍 t = Test("henry") # __setattr__被调用
## __setattr__用法1 # 在进行属性添加时,判断属性的类型,再行 class Test: def __init__(self,name): self.name = name def __setattr__(self, key, value): if type(value) is str: self.__dict__[key] = value.upper() else: print("所添加属性值为非字符串,不进行添加") t = Test("henry") t.username = "heihei" print(t.username) # HEIHEI
二,包装
包装:包装通常是对已存在的类型的一些定制,这种做法可以新建,修改,删除原有产品的功能,其它的功能保存原样
授权:授权是包装的一个特性,授权的过程既是所有更新的功能都是由新类产生的某部分来处理
# 使用继承方式完成的包装
class List(list): def append(self,P_object) if type(p_object) is str: super().append(p_object) else: print("只能添加字符串类型") l1 = List("Hello World") l1.append(18) # 无法进行添加到主字符串中 l1.append("henry") # 可以进行添加
# 实现授权的关键点是覆盖方法 __getattr__
待完成...
三,反射机制的作用
## 可插拔机制
## 动态导入模块