• 爱根,征服我的一天[isinstance,issubclass]、反射、内置attr,定制自己的数据类型


    今日重点:

    111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
    isinstance,issubclass

    # isinstance(obj,cls)检查是否obj是否是类 cls 的对象。
    # issubclass(sub,super)检查sub类是否是 super 类的派生类。
    class People:
        pass
    class List(list):
        pass
    class LIST(List):
        pass
    p=People()
    l=List()
    
    print(isinstance(p,People))  #True
    print(isinstance(l,People))  #False
    print(issubclass(List,list))     #True
    print(issubclass(People,list))   #False
    print(issubclass(LIST,List))     #True
    print(issubclass(LIST,list))     #True

    反射:getattr,setattr,delattr,hasattr

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

    #!!!!!!!!!!!!!!!!!!!!!!类也是对象!!!!!!!!!!!!!!!!!!!!!!!
    class People:
        country="china"
        def test(self):
            print("from test")
    p=People()
    print(hasattr(p,"test"))                    #True
    print(hasattr(p,"country"))                 #True
    print(hasattr(People,"test"))               #True
    print(hasattr(People,"country"))            #True
    print(getattr(p,"test"))          #<bound method People.test of <__main__.People object at 0x000000000280D7B8>>
    print(getattr(p,"123","返回值default为None,可以自己定义:這是我定义的!")) #返回值default为None,可以自己定义:這是我定义的!
    a=getattr(People,"test","返回值default为None,可以自己定义:這是我定义的!")#拿到类的函数属性的内存地址。
    a(p)                            #from test    调用。
    setattr(p,"a123","456")         #新增对象的数据属性。
    print(p.__dict__)               #{'a123': '456'}    对象的名称空间。
    print(p.a123)                   #456     查看结果。
    setattr(People,"country","China")    #修改类的变量属性。
    print(People.country,People.__dict__)    #China    查看。
    setattr(People,"abc","efg")          #新增类的变量属性。
    print(People.__dict__)               #查看名称空间。
    print(People.abc)                    #efg    检验。
    delattr(p,"a123")                    #删除p名称空间下的“a123”数据属性。
    print(p.__dict__)                    #验证,为{}
    delattr(People,"abc")                #删除类名称空间下的“abc”数据属性。
    print(People.__dict__)               #验证,没有了。
    反射的简单用途!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    import
    sys def add(): print("from add") def dell(): print("from dell") def change(): print("from change") def search(): print("from search") this_module=sys.modules[__name__] while True: choice=input("please input you choice") if not choice:continue if hasattr(this_module,choice): getattr(this_module,choice)()
                                           #反射当前模块的属性
    import sys    #类也是对象
    country="china"
    class People:
        pass
    class Animal:
        acountry="Africa"
        def walk(self):
            print("From Animal")
    def test():
        print("From test!")
    print("-------",__name__,type(__name__))   #------- client <class 'str'>
    this_module=sys.modules[__name__]
    # print("*******",this_module)    #******* <module 'client' from 'D:\PycharmProjects\py_fullstack_s4\day31\client.py'>
    # print(hasattr(this_module,"country")) #True  判断object中有没有一个name字符串对应的方法或属性
    # print(getattr(this_module,"country")) #china
    # print(hasattr(this_module,"People"))  #True
    # print(hasattr(this_module,"test"))    #True
    # print(hasattr(this_module,"acountry"))#False
    # print(hasattr(Animal,"acountry"))     #True  判断object中有没有一个name字符串对应的方法或属性
    # print(hasattr(Animal,"country"))      #False
    # getattr(this_module,"test")()           #From test!
    # setattr(this_module,"country","CHINA")  #设置模块对象下的country数据属性。
    # print(getattr(this_module,"country"))   #CHINA
    # delattr(this_module,"country")            #删除属性。
    # print("country" in this_module.__dict__)  #False

    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

    通过反射来实现插拔机制:

    #ftpclient.py 端。
    class FtpClient:
        'ftp客户端,但是还么有实现具体的功能'
        def __init__(self,addr):
            print('正在连接服务器[%s]' %addr)
            self.addr=addr
        def test(self):
            print('test')
        def get(self):
            print('get------->')
    
    
    #ftpserver.py 端。
    import ftpclient     #导入模块!
    print(ftpclient)        #ftpclient是一个模块,当然,一切皆对象,可以调用该模块下的任何属性。
    print(ftpclient.FtpClient)    #<class 'ftpclient.FtpClient'>,这是调用该模块下的一个类。
    obj=ftpclient.FtpClient('192.168.1.3')     #实例化,过程中触发该打印:正在连接服务器[192.168.1.3]
    print(obj)                                 #<ftpclient.FtpClient object at 0x0000000001E7D048> 代表该模块下的类下的对象。
    obj.test()              #同样,该对象可以调用他始祖模块中的函数,test。
    f1=ftpclient.FtpClient('192.168.1.1')    #生成实例f1。
    if hasattr(f1,'get'):                    #如果该实例f1下有“get”的方法,
        func=getattr(f1,'get')               #则拿到该函数的内存地址,
        func()                               #执行。
    # if not hasattr(f1,"abc"):
    #     print("没有该方法!")               #这是不存在该方法的情况,只是举个例子。
    else:
        print('其他逻辑')                     #没有的话,直接打印其他逻辑。

    333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333

    内置attr:__getattr__,__setattr__,__delattr__

    class People:
        def __init__(self,name):
            self.name=name
        def __setattr__(self, key, value):  #__setattr__添加/修改属性会触发它的执行。
            if not isinstance(value,str):
                raise("typeError")
            self.__dict__[key]=value  #如果这里是self.key=value,因为key,和value是字符串,self.后面不能是字符串,又者setattr(self,key,value)的话,就会递归。
                        #setattr(self,key,value)=self.key=value,会无限的递归。
    def __delattr__(self, item): #__delattr__删除属性的时候会触发他的执行。 if not isinstance(item,str): raise("typeError") self.__dict__.pop(item) def __getattr__(self,item,): #__getattr__只有在使用.调用属性且属性不存在的时候才会触发。 print(item,type(item)) p=People("egon") p.sex="male" print(p.__dict__) print(p.sex) print(p.name) print(p.xxxx) #xxxx <class 'str'> #只有通过修改字典才能完成对对象属性的修改操作,所以只有是修改self.__dict__

    444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444

    定制自己的数据类型:
    1.继承的方式:继承父类的方法,更改性能后来实现自己的功能。

    class List(list):        #继承list类的功能。
        def append(self, object):
            if not isinstance(object,int):     #改变append数据类型的判断机制,必须是int。
                raise("must be int")
            #self.append(object)               #这样会发生递归。
            super().append(object)             #继承父类list的功能。
        @property
        def mid(self):                         #新增查看中间值的功能。
            return self[int(len(self)/2)]      
    a = List([1, 2, 3])
    a.append(6)
    print(a)
    print(a.mid)
    a.pop(1)                                 #其他未定义的属性还是继承父类的方法。
    print(a)
    a.insert(0,9)
    print(a)

    2.授权的方式

    授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。

    实现授权的关键点就是覆盖__getattr__方法

    import time
    class Open:
        def __init__(self,filepath,m='r',encode='utf-8'):
            self.x=open(filepath,mode=m,encoding=encode)    #拿到文件句柄。
            self.filepath=filepath
            self.mode=m
            self.encoding=encode
        def write(self,line):
            print('f自己的write',line)
            t=time.strftime('%Y-%m-%d %X')
            self.x.write('%s %s' %(t,line))
        def __getattr__(self, item):
            return getattr(self.x,item)         #这项是保证除了write外其他方法可以调用。其实是从句柄中找句柄的方法,作为返回值。
    f=Open('b.txt','w')
    print(f)
  • 相关阅读:
    02 re模块
    24 内置模块re 正则表达式
    pickle 模块
    json模块
    命名元组
    os模块
    24 内置函数 命名元组(namedtuple) ,os ,sys,序列化,pickle,json
    functools
    ccc 音乐播放
    ccc prefab
  • 原文地址:https://www.cnblogs.com/chedanlangren/p/6758890.html
Copyright © 2020-2023  润新知