• 反射


    '''
    什么是反射:
    反射的概念是由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'))
    while True: print('studying...')
  • 相关阅读:
    【车】平安车险费用
    【光环国际】掌握项目经理12个工作流程
    【光环国际】500强公司7个项目管理工具
    数据仓库和商业智能演进五个阶段
    【技术与商业案例解读笔记】095:Google大数据三驾马车笔记
    15道最常考的SpringBoot面试题,你都遇到过哪些?
    用户画像4:标签数据开发
    plsql 传参
    shell专题(二):Shell解析器
    shell专题(三):Shell脚本入门
  • 原文地址:https://www.cnblogs.com/xuewei95/p/14703369.html
Copyright © 2020-2023  润新知