为类创建可管理的属性 概述:我们可以在实例属性的获取和设定上增加一些额外的功能,比如在设定时增加类型的检查 解决方案: 要自定义对属性的访问,一种简单的方式是将其定义为property,增加了对属性的类型检查:classPerson:definit(self,firstname):self。firstnamefirstnamegetterpropertydeffirstname(self):returnself。firstnamefirstname。setterdeffirstname(self,value):ifnotisinstance(value,str):raiseTypeError(Expectedastring)self。firstnamevaluefirstname。deleterdeffirstname(self):raiseAttributeError(Cantdeleteattribute) 上述代码中一共有三个相互关联的方法,三个方法必须名字相同,第一个是getter函数,将firstname设置为了property,并且附带绑定了两个可选方法setter和deleter方法,值的注意的是,如果没有设置property,是不能设置setter和deleter装饰器的。 property的本质就是是的修饰内容更像是一个属性(而非方法),通过对属性进行赋值和del处理会自动调用装饰器setter和deleter对应装饰的方法,实例如下:对上述例子进行操作:prPerson(小白piao)调用setterpr。firstname小白piao最sao调用setterprint(pr。firstname)小白piao最sao调用getterdelpr。firstnameAttributeError:Cantdeleteattribute如果上述例子中对pr。firstname250;会抛出TypeError:Expectedastring由此,便实现了对属性类型的限定 疑问:在init中为何是self。firstnamefirstname,而不是self。firstnamefirstname? 原因:其实由于下方设置了装饰器,所以在构造时,构造中的赋值实际上也是调用了setter方法,定义类在前,所以后边可以直接在创建对象是调用setter,这没有问题;这么做的目的,是为了在所有地方的属性设置时,都可以进行类型检查。如果在构造函数中使用‘self。firstnamefirstname’,那么此处便不会调用setter,自然不会进行类型检查,所以这样会造成判断类型的疏忽,并不是说没有其他方法完成类型的检测。这样做在一定程度了规避了代码的大量重复。 同样也可以对已经存在的get和set、delete定义为property。 讨论:实际上,property的作用是将一系列的方法进行绑定,实际上可以通过调用property属性中的fget,fset,fdel方法来完成上述操作,但实际上并不会专门去调这些方法,而是通过特殊的操作诸如赋值、打印、删除都会自动调用以上三种方法。 其实有一点很重要,只有在确实需要在访问属性时完成一些额外的工作时,才会去想到使用property。因为:一、这样写语法会对其他程序员产生困扰,代码可读性不高;二、代码的运行会变慢,实际上每个装饰器都需要额外调用函数来完成装饰动作。三、不会给设计带来真正的好处。特别是以后决定对某个属性增加额外的处理步骤是,可以再不修改已有代码的情况下将这个属性提升为一个Property。property可以用来定义需要被计算的属性:importmathclassCircle:definit(self,radius):self。radiusradiuspropertydefarea(self):returnmath。piradius2propertydefperimeter(self):return2math。piradiuscircleCircle(2)print(circle。area)print(circle。perimeter) property属性为我们提供了很多的使用的API,但是实际上,合理地使用它才是根本。不要一个类中都是property那会导致你的代码过度膨胀和丑陋,以至于不愿意读你写的代码,原因很简单,菜鸡看不明白。 我的csdn: https:blog。csdn。netweixin43520503 我的知乎: https:www。zhihu。compeoplePythonChen007 我的头条: https:www。toutiao。comcusertokenMS4wLjABAAAAowATGcWpvabSvDOw3TyZJJqpxQnwrexQzfPfGc0IOn8HRUCShGxiyqBXYuKi8C1?