程序的自我反省之----反射
一、反射的概念
是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。
这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域采用,
并在Lisp和面向对象方面取得了成绩。
二、四个可以实现自省的函数
① hasattr(object, "属性名")
判断object中有没有一个字符串对应得属性或方法,返回True或者False
② getattr (object, "属性名")
直接拿到这个name属性或方法的内存地址,找不到会报错
可以加默认参数,找不到则返回默认参数
③ setattr (object, "属性名",“属性值”)
设置属性,可以设置数据属性,也可设置函数属性
④ delattr(object, "属性名")
class BlackMedium: feture = "Ugly" def __init__(self, name, addr): self.name = name self.addr = addr def sell_hourse(self): print("{}正在卖房子".format(self.name)) def rent_hourse(self): print("{}正在租房子".format(self.name)) b1 = BlackMedium('万成置地', '万置园') print(hasattr(b1,"name")) print(getattr(b1, "sell_hourse")) s = getattr(b1, "sell_hourse")() #运行该方法 print(getattr(b1,"aaaa","没有这个属性哦"))
③和④实例:
class BlackMedium: feture = "Ugly" def __init__(self, name, addr): self.name = name self.addr = addr def sell_hourse(self): print("{}正在卖房子".format(self.name)) def rent_hourse(self): print("{}正在租房子".format(self.name)) b1 = BlackMedium('万成置地', '万置园') setattr(b1,"jinling","mygirlfriends") #添加属性,等同于 b1.jinling = "mygirlfriends" print(b1.__dict__) setattr(b1,"name", "liu") #修改属性 print(b1.__dict__) setattr(b1, 'func',lambda x : x + 1) #设置函数属性 print(b1.__dict__) print(b1.func(6)) #调用上面设置的函数 delattr(b1,"name") #删除name属性 等同于 del b1.name print(b1.__dict__)
三、为什么用反射
反射的好处就是,可以事先定义好接口,接口只有在被完成后才真正执行,这实现了即插即用,这其实是一种'后期绑定',
即你可以事先把主要的逻辑写好(只定义接口),然后后期再实现接口的功能
################################
前面四个函数也可作用于类,因为类本质上也就是对象
① __getattr__
class Foo: x = 2 def __init__(self,y): self.y = y def __getattr__(self, item): print('执行__getattr__') f1 = Foo(7) print(getattr(Foo,'x')) f1.z #当实例调用不存在的属性时会触发 __getattr__函数
② __delattr__
class Foo: x = 2 def __init__(self,y): self.y = y def __delattr__(self, item): print("正在执行__delattr__") f1 = Foo(7) del f1.x del f1.y
③ __setattr__
class Foo: x = 2 def __init__(self,y): self.y = y def __setattr__(self, key, value): print("正在执行__setattr__") self.__dict__[key] = value f1 = Foo(7) #实例化的时候创建了 y = 7,所以触发了 __setattr__ f1.z = 6 #触发__setattr__ print(f1.__dict__)
四、模块也能用反射,因为一切皆对象
import sys obj = sys.modules[__name__] #拿到当前文件的模块对象 #拿到后就能用反射啦
一个奋斗中的产品小白