关于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())

 

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

 

posted @ 2017-04-24 16:52  CrisChou  阅读(261)  评论(0编辑  收藏  举报