zoukankan      html  css  js  c++  java
  • 反射及attr使用

    反射及attr使用

    返回首页

    isinstance(obj,cls):检查是否obj是否是类cls的对象。

    class Foo(object):
        pass
    
    obj = Foo()
    isinstance(obj,Foo)

    issubclass(sub,super):检查sub类是否是super类的派生类。

    class Foo(object):
        pass
    class Bar(Foo):
        pass
    
    issubclass(Bar,Foo)

    反射

    反射是指程序可以访问、检测和修改它本身状态或行为的一种能力,也叫自省。

    在python面向对象中的反射,通过字符串的形式操作对象相关的属性,python中的一切事物都是对象(都可以使用反射)。

    四个可以实现自省的函数:这四个函数适用于类和对象(一切皆为对象,类本身也是一个对象)

    四个函数分别是:hasattr、getattr、setattr、delattr。

    attr方法

    hasattr:判断是否有要查询的属性的名字。

    class People:
        country='China'
        def __init__(self,name):
            self.name=name
        # def walk(self):
        #     print('%s is walking' %self.name)
    p=People('egon')
    # People.country  #类.数据属性
    # print(People.__dict__)
    # print(p.name) #通过实例化.函数属性的方式,调用name函数属性。
    # print(p.__dict__)
    
    #### 反射是通过字符串来访问到country属性
    #### hasattr
    print('name' in p.__dict__)
    print(hasattr(p,'name'))
    print(hasattr(p,'name1213'))
    print(hasattr(p,'country')) #p.country
    print(hasattr(People,'country')) #People.country
    print(hasattr(People,'__init__')) #People.__init__

    getattr:拿到要查询的属性的结果,并返回。getattr需要返回值。

    class People:
        country='China'
        def __init__(self,name):
            self.name=name
        def walk(self):
            print('%s is walking' %self.name)
    
    ##### getattr
    p=People('egon')
    res=getattr(p,'country') #res=p.country
    print(res)
    
    f=getattr(p,'walk') #t=p.walk
    print(f)
    
    f1=getattr(People,'walk')
    print(f1)
    
    f() #f()是walk的绑定方法,不需要传值。
    f1(p)  #f1是一个函数,所以要传值。所以把p传进去。
    
    print(getattr(p,'country','这个属性确实不存在'))  #如果有country,那么'这个属性确实不存在'不打印。
    print(getattr(p,'xxxxxxxx','这个属性确实不存在'))
    
    if hasattr(p,'walk'):
        func=getattr(p,'walk')
        func()

    setattr:设置

    class People:
        country='China'
        def __init__(self,name):
            self.name=name
        def walk(self):
            print('%s is walking' %self.name)
    
    ##### setattr
    p=People('egon')
    p.sex='male'
    print(p.sex)
    print(p.__dict__)
    setattr(p,'age',18)
    print(p.__dict__)
    print(p.age)
    print(getattr(p,'age'))

    delattr :删除

    class People:
        country='China'
        def __init__(self,name):
            self.name=name
        def walk(self):
            print('%s is walking' %self.name)
    
    ###### delattr
    p=People('egon')
    print(p.__dict__)
    del p.name
    print(p.__dict__)
    print(p.__dict__)
    delattr(p,'name')
    print(p.__dict__)

     hasattr和getattr的应用:

    import sys
    def add():
        print('add')
    
    def change():
        print('change')
    
    def search():
        print('search')
    
    def delete():
        print('delete')
    
    func_dic={
        'add':add,
        'change':change,
        'search':search,
        'delete':delete
    }
    
    while True:
        dic_key = func_dic.keys()
        print(list(dic_key))
        cmd=input('>>:').strip()
        if not cmd:continue
        if cmd in func_dic:   #hasattr()
            func=func_dic.get(cmd)   #func=getattr()
            func()
    
    #####用反射实现
    this_module=sys.modules[__name__]
    
    while True:
        dic_key = func_dic.keys()
        print(list(dic_key))
        cmd=input('>>:').strip()
        if not cmd:continue
        if hasattr(this_module,cmd):
            func=getattr(this_module,cmd)
            func()

    用反射的好处:

    一、实现可插拔机制。

    有两个程序员,一个jack,一个george,jack在写程序的时候需要用到george所写的类,但是george去跟女朋友度蜜月去了,还没有完成他写的类,jack想到了反射,使用了反射机制,jack可以继续完成自己的代码,等george度蜜月回来后再继续完成类的定义并且去实现jack想要的功能。

    反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用。这其实是一种“后期绑定”,即可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能。

    george还没实现全部功能:client端

    class FtpClient:
        "ftp客户端,但是还没有实现具体的功能"
        def __init__(self,addr):
            print("正在连接服务器[%s]" %addr)
            self.addr = addr
    
        def test(self):
            print("test")
    
        def get(self):
            print("get----》")

    不影响jack的代码编写:server端

    #from module import FtpClient
    f1=FtpClient("192,168,1,1")
    if hasattr(f1,"get")
        func_get = getattr(f1,"get")
        func_get()
    else:
        print("----》不存在此方法")
        print("处理其他的逻辑")

    二、动态导入模块(基于反射当前模块成员)

    importlib的使用,通过字符串导入模块:

    # m=input("请输入你要导入的模块:")
    # m1=__import__(m)
    # print(m1)
    # print(m1.time())
    
    #推荐使用方法
    import importlib
    t=importlib.import_module('time')
    print(t.time())

    __setattr__:在为对象设置属性的时候,就会被触发运行。

    __delattr__:在del的时候,用pop进行删除 

    #####__setattr__,__getattr__,__delattr__,
    class Foo:
        def __init__(self,x):
            self.name=x
        #
        def __setattr__(self, key, value):  #为对象设置属性时,会触发setattr的运行
            if not isinstance(value,str):   #对value的数据类型限制
                raise TypeError('must be str')
            print('----setattr---key:%s,value:%s' %(key,value))
            # print(type(key))
            # print(type(value))
            # self.key=value
            # setattr(self,key_str,value) #self.key_attribute=value
            self.__dict__[key]=value
    
        def __delattr__(self, item):
            print('delattr:%s' %item)
            print(type(item))
            # delattr(self,item)
            # del self.item
            self.__dict__.pop(item)
    
    f1=Foo('egon') #f1.name='egon'
    f1.age="18"
    print(f1.__dict__)
    print(f1.name)
    print(f1.age)
    print(f1.__dict__)
    # del f1.age
    # print(f1.__dict__)
    # print(f1.age)

    __getattr__:获取一个指令,当获取的属性不存在的时候,才会触发__getattr__。

    class Foo:
        def __init__(self,x):
            self.name=x
    
        #属性不存在的情况下才会触发
        def __getattr__(self, item):
            print('getattr-->%s %s' %(item,type(item)))
    
    f=Foo('egon')
    # print(f.name)
    print(f.xxxxxxx)

    定制自己的数据类型:也叫二次加工标准类型。

    基于继承的原理,来定制自己的数据类型(继承标准类型)

    例如:用List定义自己的类型,继承list类,使其在append操作的时候,只能append数字int类型以及insert数字int类型。

    class List(list): #List类继承list类的方法。
        def append(self, p_object):  #定义append方法,已覆盖list的append,p_object是List的append的值
            print('--->',p_object)  #打印的p_object是即将要被append进List的数据,但是这是打印List列表,不会看到p_object,因为还没有被写进List。
            if not isinstance(p_object,int):  #加类型判断,如不是int类型,返回异常。
                raise TypeError('must be int')
            super().append(p_object) #用super方法调用父类的list的append功能。将p_object写进List。
        def insert(self, index, p_object):  #对插入操作也可以更改
            if not isinstance(p_object,int):
                raise TypeError('must be int')
            super().insert(index,p_object)
    
    l=List([1,2,3])
    print(l)
    l.append(4)
    print(l)
    l.append('5')
    print(l)
    l.insert(0,-1)
    print(l)
    l.insert(0,'-1123123213')
    print(l)

    不用继承实现文件读写操作的函数功能:open

    不能用继承,来实现open函数的功能
    f=open('a.txt','w')
    print(f)
    f.write('1111111')

    授权的方式实现定制自己的数据类型:

    import time
    class Open:  #定义open类
        def __init__(self,filepath,m='r',encode='utf-8'): #init要默认生成两个参数,一个是文件路径,一个是文件读取方式。
            self.x=open(filepath,mode=m,encoding=encode)  #在init里用open,这样在Open类中,没有继承open函数。并且这个x.open才是真正被用到的
            self.filepath=filepath  #文件路径
            self.mode=m   #文件模式
            self.encoding=encode
    
        def write(self,line): #文件句柄的.write操作,
            print('f自己的write',line)   #这里并没有完成真正的write操作。
            t=time.strftime('%Y-%m-%d %X') #时间,记录写入的时间。
            print(t)
            self.x.write('%s %s' %(t,line)) #这里用self.x.write才是真正的完成write操作。
    
        def __getattr__(self,item): #用getattr获取init里x.open的各种方法,当Open类中没有read方法的时候,可以用getattr的方式获取到read的方法。
            # print('=------>',item,type(item))   #用item解决出现异常的现象,这样写不会出现异常
            return getattr(self.x,item)  #getattr通过字符串去对象里面找数据
    
    f=Open('b.txt','w')
    print(f)
    f.write('111111
    ')
    f.write('111111
    ')
    f.write('111111
    ')
    
    f=Open('b.txt','r+')
    # print(f.write)
    print(f.read)
    
    res=f.read() #self.x.read()
    print(res)
    
    print('=-=====>',f.read())
    f.seek(0)
    print(f.read())
    # f.flush()
    # f.close()

    -------- END --------

  • 相关阅读:
    React开发流程及认识
    Python整合AnaConda
    计算机显示器扩展方向调整
    python3 urlencode 和 urldecode 使用
    解决开启Vue项目缺少node_models包问题
    解决开启Vue项目缺少node_models包问题
    python中列表相加
    python炒鸡面试题
    Django中的CBV控制前后端分离模式
    selenuim使用总结
  • 原文地址:https://www.cnblogs.com/george92/p/14594163.html
Copyright © 2011-2022 走看看