python理解描述符(descriptor).docx

上传人:lao****ou 文档编号:73011 上传时间:2023-01-29 格式:DOCX 页数:9 大小:28.37KB
下载 相关 举报
python理解描述符(descriptor).docx_第1页
第1页 / 共9页
python理解描述符(descriptor).docx_第2页
第2页 / 共9页
python理解描述符(descriptor).docx_第3页
第3页 / 共9页
python理解描述符(descriptor).docx_第4页
第4页 / 共9页
python理解描述符(descriptor).docx_第5页
第5页 / 共9页
亲,该文档总共9页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《python理解描述符(descriptor).docx》由会员分享,可在线阅读,更多相关《python理解描述符(descriptor).docx(9页珍藏版)》请在第一文库网上搜索。

1、python理解描述符(descriptor).docx目录1 .Descriptor基石出12 .descriptor的作用发挥在明B33 .示例1:原始代码44 .使用property55 .使用descriptor76 .参考资料91 .Descriptor基础python中的描述符可以用来定义触发自动执行的代码,它像是一个对象属性操作(访问、赋值、删除)的代理类一样。前面介绍过的property是描述符的一种。大致流程是这样的:定义一个描述符类D,其内包含一个或多个get_()、_set_()、_delete_()方法将描述符类D的实例对象d赋值给另一个要代理的类中某个属性attr,即

2、attr=D()之后访问、赋值、删除attr属性,将会自动触发描述符类中的_get_()、_set_()_delete_()方法简言之,就是创建一个描述符类,它的实例对象作为另一个类的属性。要定义描述符类很简单,只要某个类中包含了下面一个或多个方法,就算是满足描述符协议,就是描述符类,就可以作为属性操作的代理器。classDescriptor():def_get_(self,instance,owner):.def_set_(self,instance,value):.def_delete_(self,instance):.需要注意的是,get_的返回值需要是属性值或抛异常,另外两个方法要返回

3、Noneo还需注意的是不要把delete.和_del_搞混了,前者是实现描述符协议的一个方法,后者是对象销毁函数(也常称为析构函数)。先不管这几个方法中的参数,看一个示例先:classDescriptor():def_get_(self,instance,owner):print(Hself:%sninstance:%snowner:%sH%(self,instance,owner)classS:#描述符的示例对象作为S的属性attr=Descriptor()sl=S()si.attr#访问对象属性print(-*30)S.attr#访问类属性输出结果:self:instance:owner:

4、self:instance:Noneowner:class_main_S不难看出,在访问类S中的属性attr时,表示访问描述符类的实例对象,它会自动调用描述符类中的_get_方法。在这个方法中,3个参数self、instance、owner分别对应的内容从结果中已经显示出来了。它们之间有以下等价关系:sl.attr-Descriptor.get_(S.attr,si,S)S.attr-Descriptor._get_(S.attr,None,S)所以,这里解释下get(self,instance,owner)中的三个参数:self:描述符对象自身,也就是被代理类S中的属性attrinstanc

5、e:被代理类的实例对象。所以访问类属性(class.attr)时为Noneowner:将描述符对象附加到哪个类上,其实是instance所属的类,也就是type(instance)再解释下这里相关的几个角色:Descriptor:是描述符类,也是代理者S:是另一个类,是托管类、客户类,也就是参数中的。wnerattr=Descriptor():是描述符的实例对象,attr是托管类的属性,也就参数中的selfsi:是托管类实例对象,也就是参数中的instance按照descriptor的功能,大概可以用上面的方式去定义各个角色。当然,角色的定义没什么限制。2 .descriptor的作用发挥在哪

6、当定义了一个类后,可以访问、赋值、删除它的属性,这些操作也同样适用于它的实例对象。例如Foo类:classFoo():f=Foo()a=f.bar#访问属性f.bar=b#赋值属性delf.bar#删除属性decriptor发挥作用的时候就在于执行这3类操作的时候:当访问x.d的时候,将自动调用描述符类中的get_当赋值x.d的时候,将自动调用描述符类中的_set_当删除x.d的时候,将自动调用描述符类中的_delete_考虑一下:如果x所属的类中已经定义了getattr、setattr、delattr会如何,是描述符类中的先生效,还是x自身所属类的这几个方法会生效。再继续考虑,如果x所属类没

7、有定义,但它的父类定义了这几个方法,谁会生效。可自行测试或者参考我的下一篇文章。3 .示例1:原始代码假设现在有一个Student类,需要记录stuid、name、scorelscore2score3信息。classStudent():def_init_(self,stuid,name,scorel,score2,score3):self.stuid=stuidself.name=nameself.scorel=scorelself.score2=score2self.score3=score3defreturnMe(self):return%s,%s,%i,%i,%i%(self.stuid

8、,self.name,self.scorel,self.score2,self.score3)stu=Student(20101120zmalong,67,77,88)print(stu.returnMe()但是现在有个需求,要求scorel-score3的数值范围只能是0-100分。于是修改classStudent():def_init_(self,stuid,name,scorel,score2,score3):self.stuid=stuidself.name=nameif0=scorel=100:self.scorel=scorelelse:raiseValueError(scoren

9、otin0,100)if0=score2=100:self.score2=score2else:raiseValueError(scorenotin0,100)if0=score3=100:self.score3=score3else:raiseValueError(scorenotin0,100)这个修改对于初始化Student对象时有效,但Python中属性的赋值太过自由,之后可以随意赋值:stu=Student(20101120zmalong,67,77,88)stu.scorel=-23print(stu.returnMe()4 .使用property使用Property或者自定义的g

10、etter、setter或运算符getattr_、_setattr_重载都能解决上面的问题,保证无法赋值超出0到100范围内的数值。classStudent():def_init_(self,stuid,name,scorel,score2,score3):self.stuid=stuidself.name=nameself._scorel=scorelself._score2=score2self._score3=score3defget_scorel(self):returnself._scoreldefset_scorel(self,score):if0=score=100:self,s

11、corel=scoreelse:raiseValueError(Hscorenotin0,100)defget_score2(self):returnself._score2defset_score2(self,score):if0=score=100:self.score2=scoreelse:raiseValueError(nscorenotin0,100)defget_score3(self):returnself._score3defset_score3(self,score):if0=scorescore2score3交给描述符类托管即可。fromweakrefimportWeakK

12、eyDictionaryclassScore():scoreshouldin0,100,ndef_init_(self):self.score=WeakKeyDictionaryO#self.score=defget_(self,instance,owner):returnself.scoreinstancedef_set_(self,instance,value):if0=value=100:self.scoreinstance=valueelse:raiseValueError(Hscorenotin0,100)classStudent():#托管属性定义在类级别上scorel=Score

13、()score2=Score()score3=Score()def_init_(self,stuid,name,scorel,score2,score3):self.stuid=stuidself.name=nameself.scorel=scorelself.score2=score2self.score3=score3defreturnMe(self):return%s,%s,%i,%i,%i%(self.stuid,self.name,self.scorel,self.score2,self.score3)stu=Student(“20101120”Jmalong,67,77,88)print(stu.returnMe()stu.scorel=-23很明显地,它们

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 应用文档 > 汇报材料

copyright@ 2008-2022 001doc.com网站版权所有   

经营许可证编号:宁ICP备2022001085号

本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有,必要时第一文库网拥有上传用户文档的转载和下载权。第一文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知第一文库网,我们立即给予删除!



客服