一.isinstance和issubclass
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
issubclass(sub, super)检查sub类是否是 super 类的派生类
View Code
输出结果如下
View Code
二.反射和相关的内置函数
反射是指程序可以访问、检测和修改它自己本身状态或者行为的一种能力(自省)。
而在Python中,反射其实就是通过字符串的形式访问或者修改对象的属性。这里的对象是指一切对象,类本身也是一个对象。
1 class People: 2 country = 'china' 3 def __init__(self,name,sex): 4 self.name = name 5 self.sex = sex 6 def walk(self): 7 print('walk') 8 p1 = People('silver_bullet','male') 9 print(hasattr(p1,'name')) #hasattr(*args, **kwargs) 验证有没有该属性10 print(getattr(p1,'sex')) #getattr(object, name, default=None) 获取一个属性,可以设置default11 print(setattr(p1,'age',22)) #setattr(x, y, v) 设置一个属性,返回值为None,所以用下面get方法验证12 print(getattr(p1,'age'))13 print(delattr(p1,'age')) #delattr(x, 'y') is equivalent to del x.y 删除一个属性,返回值为None14 # print(getattr(p1,'age')) #age属性已经被删除掉15 setattr(p1,'show_name',lambda self:self.name+' is excellent')#增加一个函数属性16 print(p1.show_name(p1))
模块级别的反射
1 import sys2 xxx = 1113 this_module = sys.modules[__name__] #获取当前模块4 print(hasattr(this_module,'xxx'))5 print(getattr(this_module,'xxx'))6 setattr(this_module,'yyy','12345')7 print(getattr(this_module,'yyy'))
反射的好处
实现可插拔机制。可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,即你可以事先把主要的逻辑写好(只定义接口), 然后后期再去实现接口的功能。
动态导入模块(基于反射当前模块成员)。
1 import importlib2 t = importlib.import_module('time') #通过字符串的形式导入模块,推荐使用importlib3 print(t.time()) #不推荐__import__(m),m为字符串,这个是python解释器自己使用的
三.内置函数(__attr__相关)
1 class Foo: 2 '内置函数__attr__的使用' 3 def __init__(self,name): 4 self.name = name #这个也会触发__setattr__的执行 5 def __setattr__(self, key, value): #给属性赋值都会触发__setattr__,把key和value都赋值,可以做类型判断,弥补python没有类型限制 6 self.__dict__[key] = value #直接在dict字典中添加相应的键值对即可,key和value都为字符串 7 print('from __setattr__') 8 def __delattr__(self, item): #del 操作会触发这个内置函数 9 self.__dict__.pop(item) #直接在dict字典中删除相应的键值对即可10 print('from __delattr__',type(item))# type(item)--------->str11 def __getattr__(self, item): #注意:属性获取不到,才会触发这个内置函数!!!12 print('get__attr__---->{0},{1}'.format(item,type(item)))13 14 f = Foo('silver_bullet') #触发__init__里就有一个赋值,即会触发__settattr__15 f.time = 55516 print(f.__dict__)17 print(f.time)18 del f.time #触发__del__内置函数19 print(f.__dict__)20 f.xxx #这个才会触发__getattr__的执行,没有找到xxx的属性,而现在却没有报错
四.定制自己的数据类型
继承的方式
1 class my_list(list): #基于继承 2 def __init__(self,seq): 3 for i in seq: 4 if not isinstance(i,str): 5 raise TypeError('This is not a str list') 6 else: 7 super().append(i) 8 def append(self, object: str): 9 if not isinstance(object,str):10 raise TypeError('must be str')11 super().append(object)12 @property13 def mid_value(self):14 mid_index = len(self)//215 return self[mid_index]16 17 l = my_list(['a'])18 print(l)19 l.append('1')20 print(l)21 print(l.mid_value)22 l.insert(0,4)23 print(l)
授权的方式
1 class my_list(): #基于授权 2 def __init__(self,seq): 3 for i in seq: 4 if not isinstance(i,str): 5 raise TypeError('This is not a str list') 6 self.seq = list((seq)) #使用一个中间属性self.seq保存这个列表 7 def __str__(self): #override __str__,才能够打印列表的显示,否则打印的是一个对象地址 8 return str(self.seq) 9 def append(self, object: str): #重新定制这个append10 if not isinstance(object,str):11 raise TypeError('must be str')12 self.seq.append(object) #实际上是在这里使用13 @property14 def mid_value(self): #定制一个属性,返回中间值。15 mid_index = len(self.seq)//216 return self.seq[mid_index]17 def __getattr__(self, item): #其余方法都使用list默认的18 func = getattr(self.seq,item) #直接返回getattr的函数名19 return func20 def __getitem__(self, item): #加上以下三个item操作,才能够支持索引,切片,赋值和del删除21 return self.seq[item]22 def __setitem__(self, key, value):23 self.seq[key] = value24 def __delitem__(self, key):25 self.seq.pop(key)26 27 28 l = my_list(['a'])29 print(l)30 l.append('1')31 print(l[1])32 print(l.mid_value)33 l.insert(0,4)34 l[0]='123'35 print(l)36 print(l[1:])
五.给日志文件加时间头
使用授权的方式重写open
1 import time 2 class Open: 3 'override File write' 4 def __init__(self,path,mode = 'r',encoding = 'GBK'): 5 self.fw = open(path,mode=mode,encoding=encoding) #这里要写成位置参数的形式,取到文件句柄赋值给self.f 6 def write(self,line): 7 now_time = time.strftime('%Y-%m-%d-%X') #字符串形式显示time时间 8 self.fw.write('{0}\n'.format(now_time)) #添加日志文件的时间头 9 self.fw.write(line) #写想要输入到文件里面的内容10 def __getattr__(self, item): #不想要改写的地方定义在__getattr__中,找不到的属性会触发这个内置函数11 func = getattr(self.fw,item) #通过getattr的方法,将函数名的入口地址获取到并且返回12 return func13 14 f = Open('a.txt','w+') #触发__init__方法15 for i in range(2):16 f.write('11111111111\n')17 time.sleep(0.5)18 f.seek(0)19 print(f.readlines())
http://www.cnblogs.com/yangming111/p/6758328.html