''' 什么是反射: 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省) ''' # isinstance(obj, cls)检查obj是否是类cls的对象 class Foo: pass obj = Foo() print(isinstance(obj, Foo)) # True # issubclass(sub, super)检查sub类是否是super类的派生类 class A: pass class B(A): pass b1 = B() print(issubclass(B, A)) # True print(isinstance(b1, A)) # True,b1是B类的实例,B是A类的子类 print(type(b1)) # 通过实例查看类,<class '__main__.B'> '''四个可以实现自省的函数,下列方法适用于类和对象''' class Black_Medium: feture = 'Ugly' def __init__(self, name, addr): self.name = name self.addr = addr def sell_hourse(self): print('%s正在卖房子' % self.name) def rent_hourse(self): print('%s正在出租房子' % self.name) b1 = Black_Medium('乐有家', '深圳湾') # ①hasattr(object, name)判断object中有没有一个name字符串对应的方法或属性 print(hasattr(b1, 'name')) # True;b1.name--->b1.__dict__['name'] print(hasattr(b1, 'sell_hourse')) # True,其实也相当于检测b1能否调用所对应的数据属性和函数属性 # ②getattr(object, name, default=None) print(getattr(b1, 'name')) # '乐有家' print(getattr(b1, 'sell_hourse')) # <bound method Black_Medium.sell_hourse of <__main__.Black_Medium object at 0x000001BC3D4C0160>> print(getattr(b1, 'name1', '没找到')) # 当寻找的方法或属性不存在时,打印第三个参数;如果不存在且不传入第三个参数,那么会报错 # ③setattr(x, y, v)添加修改属性 setattr(b1, 'sb', 18) # 相当于b1.sb=18 setattr(b1, 'name', 'SB') setattr(b1, 'func', lambda x: x+1) # 添加函数属性 print(b1.func(2)) setattr(b1, 'rent_hourse', lambda x: x**2) # 修改函数属性 print(b1.rent_hourse(3)) print(b1.__dict__) # {'name': 'SB', 'addr': '深圳湾', 'sb': 18} # ④delattr(x, y)删除属性 delattr(b1, 'sb') # 相当于del b1.sb # delattr(b1, 'aaa') # 不存在则报错 print(b1.__dict__) # {'name': 'SB', 'addr': '深圳湾'} '''反射的好处''' # 实现可插拔机制(可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能) class FtpClient: '''ftp客户端,但是还没有实现具体的功能''' def __init__(self, addr): self.addr = addr print('正在连接服务器%s' % self.addr) def get(self): '''后续又实现了该功能''' print('正在获取文件信息...') # 另一个模块代码 # from day51 import FtpClient # # f1 = FtpClient('198.1.1.1') # if hasattr(f1, 'get'): # func_get = getattr(f1, 'get') # func_get() # else: # print('方法未实现') # 模块信息为字符串形式的第一种导入方法 # m = __import__('my_module.web.web1.web2.cal') # print(m) # <module 'my_module' from 'C:\Users\XHP\PycharmProjects\python_quanzhan\s1\my_module\__init__.py'>显示最顶级文件目录的信息 # print(m.web.web1.web2.cal.add(3, 4)) # 模块信息为字符串形式的第二种导入方法(最好是用这种) # import importlib # n = importlib.import_module('my_module.web.web1.web2.cal') # print(n) # <module 'my_module.web.web1.web2.cal' from 'C:\Users\XHP\PycharmProjects\python_quanzhan\s1\my_module\web\web1\web2\cal.py'>显示所导入模块的信息 # print(n.add(3, 4)) # 当所导入模块有私有方法时该如何导入 # from my_module.web.web1.web2.cal import add,_add1 # 当import*的时候,_add1()会报错(就唯独不能*导入) # print(add(3, 3)) # print(_add1(3, 3)) # 当前模块的反射 # import sys '''sys.modules是一个全局字典,该字典是python启动后就加载在内存中。每当程序员导入新的模块,sys.modules都将记录这些模块。字典sys.modules对于加载模块起到了缓冲的作用。当某个模块第一次导入,字典sys.modules将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快了程序运行的速度''' # x = 1 # print(sys.modules[__name__]) # <module '__main__' from 'C:/Users/XHP/PycharmProjects/python_quanzhan/s1/day55.py'> # obj = sys.modules[__name__] # print(hasattr(obj, 'x'))