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 --------

  • 相关阅读:
    [ERR] Node 10.211.55.8:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    PAT A1137 Final Grading (25 分)——排序
    PAT A1136 A Delayed Palindrome (20 分)——回文,大整数
    PAT A1134 Vertex Cover (25 分)——图遍历
    PAT A1133 Splitting A Linked List (25 分)——链表
    PAT A1132 Cut Integer (20 分)——数学题
    PAT A1130 Infix Expression (25 分)——中序遍历
    PAT A1142 Maximal Clique (25 分)——图
    PAT A1141 PAT Ranking of Institutions (25 分)——排序,结构体初始化
    PAT A1140 Look-and-say Sequence (20 分)——数学题
  • 原文地址:https://www.cnblogs.com/george92/p/14594163.html
Copyright © 2011-2022 走看看