isinstance(obj,cls)检查是否是obj或cls类的对象
1 class Foo: 2 pass 3 obj=Foo() 4 print(isinstance(obj,Foo)) 5 运行结果是True检查sub类是否是super类的派生类 6 class Foo: 7 pass 8 class Bar(Foo): 9 pass 10 print(issubclass(Bar,Foo)) 11 运行结果是True
反射?
反射是指程序可以访问,检测和修改它本身状态或行为的一种能力(自省)
python面向对象中的反射通过字符串形式操作对象相关的属性。反射共有四个函数加以使用:
hasattr,getattr,setattr,delattr
1 class Test: 2 ceshi="这是一个测试段" 3 def test1(self): 4 print("反射测试") 5 def ceshi1(self): 6 print("实例代码") 7 print(hasattr(Test,"ceshi")) 8 #setattr的使用示例 9 print(Test.__dict__) 10 setattr(Test,"ceshi","修改内容") 11 setattr(Test,"ceshi2","添加内容") 12 print(Test.__dict__) 13 getattr的使用方式示例 14 print(getattr(Test,"ceshi")) 15 print(getattr(Test,"name","没有此项")) 16 #getattr可以通过字符串获取类字典内的值,在使用是可以传入三个参数,第三个参数为为获取到值后的返回值,可以自定义内容 17 delattr(Test,"ceshi") 18 print(Test.__dict__) 19 #delattr是删除类中的一个属性
反射的使用实例:
1.实现程序开发的可插拔。也就是可以先定义接口,然后补充接口功能,不影响程序的向下开发
示例:
公司需要开发一个FTP,开发人员一负责开发服务端,开发二负责开发客户端,当开发一没有定义下载的方法时,开发二可以使用已经定义好的方法名字,加判断,使用服务端方法,继续向下开发,不会影响程序的整体进度,当开发一重新对方法定义后,开发二不用做修改,可以直接使用服务端方法
#这是服务端 class Ftpserver: def __init__(self,addr): self.addr=addr def get(self): print("下载操作") #这是客户端 from FTP import Ftpserver f1=Ftpserver("192.168.1.100") if hasattr(f1,"get"): func=getattr(f1,"get") func() else: print("没有这个方法")
2.动态导入模块
__getattr__,__setattr__,__delattr__ 方法的解释使用
__getattr__(self,name):当属性name被访问且对象没有响应的属性时被自动调用
__setattr__(self,name,value):当试图给属性name赋值时会自动调用
__delattr__(self,name):当试图删除属性name时被自动调用
示例:
class Rectangle: def __init__(self): self.width=0 self.height=0 def __setattr__(self, name, value):#修改或者添加值的时候会触发setattr运行 if name =="size": self.width,self.height=value else: self.__dict__[name]=value def __getattr__(self, name):#当调用的方法不存在时,运行getattr if name=="size": return self.width,self.height else: raise AttributeError r1=Rectangle() r1.height=10 r1.width=100 #print(r1.__dict__) print(r1.__setattr__("size1","10")) r1.__dict__["lzh"]=28 print(r1.__dict__) print(r1.rea)#调用不存在方法,触发__getattr__运行,报错
二次加工标准类型
基于继承的二次包装
python的标准类型提供了很多丰富的使用模式,但是有时候我们需要自己定制一些类型的使用,比如列表添加时限制添加值的类型等:
示例:
class List(list):#继承list类 def append(self, object: int): if not isinstance(object,int):#定制数据类型,判断值 raise TypeError#错误后自动报错 super(List, self).append(object)#使用super调用基类 l=List([1,2,3,4]) l.append(1) print(l)
基于授权的标准类定义
基于授权的类定义,可以添加新建删除原有类的方法,其他保持原样。实现授权的关键点在于使用__getattr__特殊方法的使用
示例:
class List:#新建一个新的类,不继承原list任何属性 def __init__(self,seq):#建立一个绑定方法,设立初始值 self.seq=seq def append(self,value):#定义一个append方法 if isinstance(value,int):#判断类型 self.seq.append(value)#self.seq的意义在于调用原list方法,授权 else: raise TypeError def __getattr__(self, item):#此方法的使用是授权的重点,意义在于没有调用的属性时运行此处方法 return getattr(self.seq,item) @property def mid(self):#定制一个取列表中间值的方法 return self.seq[len(self.seq)//2],type(self.seq[len(self.seq)//2]) l1=List([1,2,3]) print(l1.__dict__) print(getattr(l1,"seq")) l1.append(11) l1.append(12) l1.append(0) l1.pop(0)
基本的序列和映射规则
__getitem__ ,__setitem__,__delitem__
__getitem__(self,key):这个方法返回与所给键对应的值。
__setitem__(self,key,value):这个方法按一定的方式存储和key相关的value,该值可使用__getitem__获取。当然,只能为可以修改的对象定义这个方法。
__delitem__(self,key):这个方法在对一部分对象使用del语句时被调用,同时必须删除和键相关的键
示例:
class test: def __init__(self,name): self.name=name def __getitem__(self, item): return self.__dict__(item) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): self.__dict__.pop(key) t1=test("lzh") t1.__dict__["age"]=18 t1.age=20 print(t1.age) print(t1.__dict__)
__slost__方法的使用
__slost__方法的优点:1,节省内存空间
2,可以在一定程度上限制数据属性的添加使用。
示例:
class Foo: __slots__ = ["z","x"]#在查看类的字典时,会是一个列表 f1=Foo() f1.z=1#必须slost列表中定义的数据属性名称 f1.x=10 print(Foo.__dict__) print(f1.z,f1.x) #在使用__slost__时,没有对象字典,只有一个类的字典可以查到
__del__析构函数
import time class Open: def __init__(self,filepath,m=‘r‘,encode=‘utf-8‘): self.f=open(filepath,mode=m,encoding=encode) def write(self,line): pass def __getattr__(self, item): return getattr(self.f,item) def __del__(self):#此处使用析构函数,触发一个删除操作,当函数需要删除值或者关闭一个文件时,都是在删除一个内存引用计数。 print("——>del") self.f.close() # f=Open(‘b.txt‘,‘w‘) f1=f#这时候有2个引用关系,所以del在删除时不会立即执行 del f#删除操作,删除引用计数,在程序运行完之前自己解除引用,当没有此操作时,程序会在运行结束后,由解释器内存回收机制直接回收 print(">>>>")
__next__,__iter__迭代器协议
示例:
#定义一个range方法,实现其功能 class rang: def __init__(self,start,stop): self.start=start self.stop=stop def __iter__(self): return self def __next__(self): if self.start==self.stop: raise StopIteration self.start+=1 return self.start-1 r1=rang(1,10) for i in r1: print(i)
__call__使用方法
对象通过提供__call__(slef, [,*args [,**kwargs]])方法可以模拟函数的行为,如果一个对象x提供了该方法,就可以像函数一样使用它,也就是说x(arg1, arg2...) 等同于调用x.__call__(self, arg1, arg2) 。
模拟函数的对象可以用于创建防函数(functor) 或代理(proxy)
1 class Foo: 2 def __init__(self,num): 3 self.num=num 4 def __call__(self, *args, **kwargs):#定义__call__函数方法 5 print(args,kwargs) 6 f1=Foo(100) 7 f1(120,130,a=10,y=200)#在调用时,不需要加括号调用。