• 关于python反射机制和定制自己的数据类型


    关于isinstance:

    isinstance是python内置的数据类型判断函数,其作用就是判断一个数值的数据类型为和类型。

    isinstance(value,type)#返回bool类型

    关于issubclass:

    issubclass是用于基础关系的判断,一般用于判断子类是否继承自父类

    issubclass(subclass,superclass)#返回bool类型

    接下来的python内置的类的反射机制

    getattr可以用于使用字符串的方式访问

    class Add():
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def func(self):
            print('from func')
    a=Add('cris',20)
    print(getattr(a,'name'))
    返回结果为
    cris
    print(setattr())
    View Code

    当然getattr还有第三个默认参数,getattr(a,'gande','None'),当get对象不存在的时候就会返回第三个参数比如None

    setattr用字符串的形式写入变量名和值,第一个参数是对象

     1 class Add():
     2     def __init__(self,name,age):
     3         self.name=name
     4         self.age=age
     5     def func(self):
     6         print('from func')
     7 a=Add('cris',20)
     8 print(getattr(a,'name'))
     9 setattr(a,'gande','')
    10 print(a.gande)
    View Code

    delattr可以用于以字符串的方式删除字段

    class Add():
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def func(self):
            print('from func')
    a=Add('cris',20)
    print(getattr(a,'name'))
    setattr(a,'gande','')
    print(a.gande)
    print(delattr(a,'gande'))
    print(a.gande)
    View Code

    hassttr可以判断是否存在这个对象,返回bool类型

    class Add():
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def func(self):
            print('from func')
    a=Add('cris',20)
    # print(getattr(a,'gande','None'))
    # setattr(a,'gande','男')
    # print(a.gande)
    # print(delattr(a,'gande'))
    print(hasattr(a,'gande'))

    执行结果为false

    内置的attr:

    __getattr__,

    类内部的__getattr__表面上看是用来返回值的,其实只有当变量访问不存在的字段的时候才会执行这段函数

    class Add:
        def __init__(self,name):
            self.name=name
        def __getattr__(self, key):  # 属性不存在情况下才会触发这个运行
            print('这个属性不存在')
    
    a=Add('cris')
    a.gande

    因为试图访问一个不存在的对象所以执行结果为‘这个属性不存在’

    __setattr__,

    也是类中的内置函数,当实例化一个对象传入参数,或者外部写入变量和值的时候会执行这段函数

    class Add:
        def __init__(self,name):
            self.name=name
        # def __getattr__(self, key):  # 属性不存在情况下才会触发这个运行
        #     print('这个属性不存在')
        def __setattr__(self, key, value):
            print('我在写入内容')
            self.__dict__[key]=value
    a=Add('cris')

    由此可以看出这个代码是用于内部写入参数的,如果这样的话那可不可以用他来控制整个类的参数类型限制呢?我们来试试。

    class Add:
        def __init__(self,name):
            self.name=name
        # def __getattr__(self, key):  # 属性不存在情况下才会触发这个运行
        #     print('这个属性不存在')
        def __setattr__(self, key, value):
            print('我在写入内容')
            if not isinstance(value,str):
                raise TypeError('类型错误')
            self.__dict__[key]=value
    
    a=Add(123)

    当我们传入一个整形参数的时候结果发现抛出了类型错误

    __delattr__,

    当外部删除类中的字段的时候会执行这个函数

    class Add:
        def __init__(self,name):
            self.name=name
        # def __getattr__(self, key):  # 属性不存在情况下才会触发这个运行
        #     print('这个属性不存在')
        def __setattr__(self, key, value):
            print('我在写入内容')
            if not isinstance(value,str):
                raise TypeError('类型错误')
            self.__dict__[key]=value
        def __delattr__(self, item):
            print('我在删除元素')
            del self.__dict__[item]
    
    a=Add('cris')
    print(a.name)
    del a.name
    print(a.name)

    结果一目了然

    接下来我们来进入下一个环节,如何定制自己的数据类型

    1.继承的方式

    我们来定制一个自己的列表函数

    class my_list(list):
        def append(self, p_object):
            print('我在添加%s'%p_object)
            if not isinstance(p_object,int):
                raise TypeError('必须是整形')
            super().append(p_object)
    l=my_list([1,2,3,4])
    l.append('2')

    利用isinstance我们成功的限制了list函数的添加元素类型必须为int类型否则报错,以上方法是利用类的继承来实现的

    2.授权的方式

    我们来定制一个写入文件的函数,在写入内容的同时写入当前系统时间,用来模仿任务日志

    import time
    class Open:
        def __init__(self,filepath,m='r',encoding='utf8'):
            self.io=open(filepath,mode=m,encoding=encoding)
            self.filepath=filepath
            self.mode=m
            self.encoding=encoding
        def write(self,line):
            t=time.strftime('%y-%m-%d %x')
            self.io.write('%s %s'%(t,line))
        def __getattr__(self, item):
            return getattr(self.io,item)
    f=Open('001.txt','w')
    f.write('xxxxxx')

    我们来测试一下其他的功能

    class Open:
        def __init__(self,filepath,m='r',encoding='utf8'):
            self.io=open(filepath,mode=m,encoding=encoding)
            self.filepath=filepath
            self.mode=m
            self.encoding=encoding
        def write(self,line):
            t=time.strftime('%y-%m-%d %x')
            self.io.write('%s %s'%(t,line))
        def __getattr__(self,item):
            return getattr(self.io,item)
    f=Open('001.txt','w')
    f.write('xxxxxx')
    f.seek(0)
    r=Open('001.txt','r')
    print(r.read())




    用授权定制一个只能传入字符串的list
    class my_list:
        def __init__(self,list):
            self.list=[]
            self.list.extend(list)
        def append(self,value):
            if not isinstance(value,str):
                raise TypeError('必须是字符串类型')
            self.list.append(value)
        @property
        def check_cent_value(self):
            return self.list[int(len(self.list)/2)]
        def __getattr__(self, item):
            return getattr(self.list,item)
    l=my_list(['a','b','c','d','e','f'])
    print(l.check_cent_value)
    print(l.pop())

    如果你看到了这段代码又看不懂没关系,这他妈本来就是给我自己看的

     

  • 相关阅读:
    Docker-Compose搭建单体SkyWalking 6.2
    Docker搭建MySQL主从集群,基于GTID
    【简记】修改Docker数据目录位置,包含镜像位置
    【拆分版】Docker-compose构建Kibana单实例,基于7.1.0
    【拆分版】Docker-compose构建Logstash多实例,基于7.1.0
    【拆分版】Docker-compose构建Zookeeper集群管理Kafka集群
    命令行模式和python交互模式
    详解 HTTPS、TLS、SSL、HTTP区别和关系
    windows下如何查看进程、端口占用、杀死进程教程
    pycharm最常用的快捷键总结
  • 原文地址:https://www.cnblogs.com/crischou/p/6757714.html
Copyright © 2020-2023  润新知