• 反射attr以及模块动态导入


    一、实现自省的四个函数

    1、hasattr判断一个对象中有没有一个name字符串对应的方法或属性

    class BlackMedium:
        feture="Ugly"
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
        def sell_house(self):
            print("%s 正在卖房子,傻逼才买呢" %self.name)
        def rent_house(self):
            print("%s 正在租房子,傻逼才租呢" % self.name)
    b1=BlackMedium("中原地产","北京通州梨园")
    #b1.name---->b1.__dic__["name"]
    print(hasattr(b1,"name"))#就是检测实例的属性字典里面有没有name这个key
    print(hasattr(b1,"sell_house"))#但是b1的属性字典里面没有sell_house,也是True啊
    #所以hasattr是检查实例到底能不能调用这个属性,能调用就True
    
    C:python35python3.exe D:/pyproject/day26/反射.py
    
    True
    
    True

    如果没有则返回False

    2、getaddr  获取实例的属性

    class BlackMedium:
        feture="Ugly"
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
        def sell_house(self):
            print("%s 正在卖房子,傻逼才买呢" %self.name)
        def rent_house(self):
            print("%s 正在租房子,傻逼才租呢" % self.name)
    b1=BlackMedium("中原地产","北京通州梨园")
    print(getattr(b1,"name"))#获取实例的数据属性
    print(getattr(b1,"addr"))#获取实例的数据属性
    func=getattr(b1,"sell_house")#获取实例的函数属性,赋值给func
    func()
    
    C:python35python3.exe D:/pyproject/day26/反射.py
    
    中原地产
    
    北京通州梨园
    
    中原地产 正在卖房子,傻逼才买呢

    如果需要获取的实例的属性没有的话就报错了

    class BlackMedium:
        feture="Ugly"
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
        def sell_house(self):
            print("%s 正在卖房子,傻逼才买呢" %self.name)
        def rent_house(self):
            print("%s 正在租房子,傻逼才租呢" % self.name)
    b1=BlackMedium("中原地产","北京通州梨园")
    print(getattr(b1,"name"))#获取实例的数据属性
    print(getattr(b1,"addr"))#获取实例的数据属性
    func=getattr(b1,"sell_house11111111111111")#获取实例的函数属性,赋值给func
    func()
    
    AttributeError: 'BlackMedium' object has no attribute 'sell_house11111111111111'

    可以加一个默认的参数,如果getaddr获取的属性不存在的话就返回你定义的那个

    class BlackMedium:
        feture="Ugly"
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
        def sell_house(self):
            print("%s 正在卖房子,傻逼才买呢" %self.name)
        def rent_house(self):
            print("%s 正在租房子,傻逼才租呢" % self.name)
    b1=BlackMedium("中原地产","北京通州梨园")
    print(getattr(b1,"name"))#获取实例的数据属性
    print(getattr(b1,"addr"))#获取实例的数据属性
    print(getattr(b1,"sell_housesss","1111"))#获取实例的函数属性,赋值给func
    
    C:python35python3.exe D:/pyproject/day26/反射.py
    
    中原地产
    
    北京通州梨园
    
    1111

    3、setaddr给对象(实例)设置属性

    class BlackMedium:
        feture="Ugly"
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
        def sell_house(self):
            print("%s 正在卖房子,傻逼才买呢" %self.name)
        def rent_house(self):
            print("%s 正在租房子,傻逼才租呢" % self.name)
    b1=BlackMedium("中原地产","北京通州梨园")
    # b1.sb=True
    setattr(b1,"sb",True)#给b1这个实例增加一个sb的属性,值为True
    setattr(b1,"加油",111)
    setattr(b1,"name","大sb")#如果之前有name的属性,会覆盖之前的属性值
    print(b1.__dict__)#查看实例b1的属性字典
    
    C:python35python3.exe D:/pyproject/day26/反射.py
    
    {'name': '大sb', 'sb': True, '加油': 111, 'addr': '北京通州梨园'}

    用setaddr给对象(实例)设置函数属性

    class BlackMedium:
        feture="Ugly"
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
        def sell_house(self):
            print("%s 正在卖房子,傻逼才买呢" %self.name)
        def rent_house(self):
            print("%s 正在租房子,傻逼才租呢" % self.name)
    b1=BlackMedium("中原地产","北京通州梨园")
    setattr(b1,"func",lambda x:x+1)
    setattr(b1,"func1",lambda self:self.name+"sb")
    print(b1.__dict__)
    print(b1.func)
    print(b1.func(6))
    print(b1.func1(b1))
    
    C:python35python3.exe D:/pyproject/day26/反射.py
    
    {'func1': <function <lambda> at 0x0000000000D32400>, 'func': <function <lambda> at 0x0000000000D321E0>, 'addr': '北京通州梨园', 'name': '中原地产'}
    
    <function <lambda> at 0x0000000000D321E0>
    
    7
    
    中原地产sb

    4、delattr    删除实例的属性

    class BlackMedium:
        feture="Ugly"
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
        def sell_house(self):
            print("%s 正在卖房子,傻逼才买呢" %self.name)
        def rent_house(self):
            print("%s 正在租房子,傻逼才租呢" % self.name)
    b1=BlackMedium("中原地产","北京通州梨园")
    # b1.sb=True
    setattr(b1,"sb",True)#给b1这个实例增加一个sb的属性,值为True
    setattr(b1,"加油",111)
    setattr(b1,"name","大sb")#如果之前有name的属性,会覆盖之前的属性值
    print(b1.__dict__)#查看实例b1的属性字典
    del b1.sb#删除b1的属性
    del b1.加油#删除b1的属性
    print(b1.__dict__)
    
    C:python35python3.exe D:/pyproject/day26/反射.py
    
    {'sb': True, 'addr': '北京通州梨园', '加油': 111, 'name': '大sb'}
    
    {'addr': '北京通州梨园', 'name': '大sb'}
    class BlackMedium:
        feture="Ugly"
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
        def sell_house(self):
            print("%s 正在卖房子,傻逼才买呢" %self.name)
        def rent_house(self):
            print("%s 正在租房子,傻逼才租呢" % self.name)
    b1=BlackMedium("中原地产","北京通州梨园")
    # b1.sb=True
    setattr(b1,"sb",True)#给b1这个实例增加一个sb的属性,值为True
    setattr(b1,"加油",111)
    setattr(b1,"name","大sb")#如果之前有name的属性,会覆盖之前的属性值
    print(b1.__dict__)#查看实例b1的属性字典
    # del b1.sb#删除b1的属性
    # del b1.加油#删除b1的属性
    delattr(b1,"sb")
    print(b1.__dict__)
    
    C:python35python3.exe D:/pyproject/day26/反射.py
    
    {'sb': True, 'addr': '北京通州梨园', 'name': '大sb', '加油': 111}
    
    {'addr': '北京通州梨园', 'name': '大sb', '加油': 111}

    上面这四种attr都是在自己这里找,使用它们来实现自省的功能,就是自我反省,自我检查的意思,从自己这里找

    5、反射的具体应用

    gouguoqi负责开发ftp_client这个类,但是出去旅游去了,代码只写了一半儿
    
    class FtpClient:
        'ftp客户端,但是还么有实现具体的功能'
        def __init__(self,addr):
            print('正在连接服务器[%s]' %addr)
            self.addr=addr 

    miaoye负责一个其他的类,但是跟gouguoqi是一个团队的,虽然ftp_client没有写好,但是很不影响miaoye编写代码

    from ftp_client import FtpClient
    
    f1=FtpClient('1.1.1.1')
    # f1.put()#由于人家类还写好,直接调用就报错了
    
    if hasattr(f1,'put'):#所以先判断一下人家到底写好了没有
        func_get=getattr(f1,'put')
        func_get()
    else:
        print('其他的逻辑')
    
    
    C:python35python3.exe D:/pyproject/day26/miaoye使用者.py
    
    正在连接服务器[1.1.1.1]
    
    正在上传文件

    过了半年,gouguoqi度假回来了,写好了ftp_clent这个类,miaoye那里的代码都不用动,直接就可以用了

    gouguoqi的ftp_client

    class FtpClient:
        'ftp客户端,但是还么有实现具体的功能'
        def __init__(self,addr):
            print('正在连接服务器[%s]' %addr)
            self.addr=addr
        def put(self):
            print('正在上传文件')

    miaoye的

    from ftp_client import FtpClient
    
    f1=FtpClient('1.1.1.1')
    # f1.put()#由于人家类还写好,直接调用就报错了
    
    if hasattr(f1,'put'):#所以先判断一下人家到底写好了没有
        func_get=getattr(f1,'put')
        func_get()
    else:
        print('其他的逻辑')
    
    C:python35python3.exe D:/pyproject/day26/miaoye使用者.py
    
    正在连接服务器[1.1.1.1]
    
    正在上传文

    这就叫做可插拔式设计

    二、动态导入模块

    1、__import__导入的只导入到顶级,就是导入了m1,

    module_t=__import__("m1.t")
    print(module_t)
    
    C:python35python3.exe D:/pyproject/day26/动态模块导入.py
    
    <module 'm1' (namespace)>
    
     
    
    module_t=__import__("m1.t")
    print(module_t)
    module_t.t.test1()
    
    C:python35python3.exe D:/pyproject/day26/动态模块导入.py
    
    <module 'm1' (namespace)>
    
    test1
    
     
    
     
    
    m=__import__("test")
    print(m)

    2、补充:

    把t模块中的所有的方法都导入过来

    t模块中的内容

    def test1():
        print("test1")
    def test2():
        print("test2")
    
     
    
    from m1.t import *
    test1()
    test2()
    
    C:python35python3.exe D:/pyproject/day26/动态模块导入.py
    
    test1
    
    test2

    那我们把t模块中的test2前面加个下划线,变为私有属性之后import *就不能导入了

    def test1():
        print("test1")
    def _test2():
        print("test2")
    
     
    
    NameError: name 'test2' is not defined

    但是我们可以换种导入的方式,就可以正常导入了

    from m1.t import test1,_test2
    test1()
    _test2()
    
    C:python35python3.exe D:/pyproject/day26/动态模块导入.py
    
    test1
    
    test2

    3、利用模块的方式   import importlib

    这种方式直接就可以导入到t了。而不是下面这样

    module_t=__import__("m1.t")
    print(module_t)
    module_t.t.test1()
    
     
    
     
    
     
    
    import importlib
    m=importlib.import_module("m1.t")
    print(m)
    m.test1()
    m._test2()
    
    C:python35python3.exe D:/pyproject/day26/动态模块导入.py
    
    <module 'm1.t' from 'D:\pyproject\day26\m1\t.py'>
    
    test1
    
    test2
  • 相关阅读:
    第40次全国计算机等级考试监考
    [再寄小读者之数学篇](2014-07-27 打印错误吧)
    日积月累的名典[2014-10-7]
    2014年全球“高被引科学家”数学类名单
    年轻尼姑的19句话
    PostgreSQL的 initdb 源代码分析之十六
    PostgreSQL的 initdb 源代码分析之十五
    PostgreSQL的 initdb 源代码分析之十四
    PostgreSQL的 initdb 源代码分析之十三
    PostgreSQL的 initdb 源代码分析之十二
  • 原文地址:https://www.cnblogs.com/gouguoqilinux/p/9208549.html
Copyright © 2020-2023  润新知