老师参与

装饰器

定几个小目标 发表于2019年04月26日
<p>类里的这个装饰器的形参应该是两个函数?这个装饰器其实装饰了两个函数,一个是系统默认的赋值操作,一个是在装饰器下自己写的函数,大概是这样吧</p>
2 回复

    1楼

  • 王恺-南开大学 发表于2019年04月26日
    1 | 1 | 举报
    <p>以下面的例子解释一下:<br ></p><p><code class="brush:python;toolbar:false" >import&nbsp;datetime class&nbsp;Student:&nbsp;#定义Student类 &nbsp;&nbsp;&nbsp;&nbsp;@property &nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;score(self):&nbsp;#用@property装饰器定义一个用于获取score值的方法 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;self._score &nbsp;&nbsp;&nbsp;&nbsp;@score.setter &nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;score(self,&nbsp;score):&nbsp;#用score.setter定义一个用于设置score值的方法 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;score&lt;0&nbsp;or&nbsp;score&gt;100:&nbsp;#不符合0~100的限定条件 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print('成绩必须在0~100之间!') &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self._score=score &nbsp;&nbsp;&nbsp;&nbsp;@property &nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;age(self):&nbsp;#用@property装饰器定义一个用于获取age值的方法 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;datetime.datetime.now().year-self.birthyear if&nbsp;__name__=='__main__': &nbsp;&nbsp;&nbsp;&nbsp;stu=Student()&nbsp;#创建Student类对象stu &nbsp;&nbsp;&nbsp;&nbsp;stu.score=80&nbsp;#将stu对象的score属性赋值为80 &nbsp;&nbsp;&nbsp;&nbsp;stu.birthyear=2000&nbsp;#将stu对象的birthyear属性赋值为1990 &nbsp;&nbsp;&nbsp;&nbsp;print('年龄:%d,成绩:%d'%(stu.age,stu.score)) &nbsp;&nbsp;&nbsp;&nbsp;#stu.age=19&nbsp;#取消前面的注释符则会报错 &nbsp;&nbsp;&nbsp;&nbsp;stu.score=105&nbsp;#将stu对象的score属性赋值为105 &nbsp;&nbsp;&nbsp;&nbsp;print('年龄:%d,成绩:%d'%(stu.age,stu.score))</code></p><p>程序执行完毕后,将在屏幕上输出如下结果:</p><p><code class="brush:python;toolbar:false" >年龄:18,成绩:80 成绩必须在0~100之间! 年龄:18,成绩:80</code></p><p>直接使用@property就可以定义一个用于获取属性值的方法(即getter)。例如,代码中的第3至5行以及第12至14行,分别定义了用于获取score和age属性值的方法。</p><p>如果要定义一个设置属性值的方法(setter),则需要使用名字“@属性名.setter”的装饰器。例如,代码中的第6至11行,定义了用于设置score属性值的方法,对应的装饰器名字为“@score.setter”。</p><p>如果一个属性只有用于获取属性值的getter方法,而没有用于设置属性值的setter方法,则该属性是一个只读属性,只允许读取该属性的值、而不能设置该属性的值。例如,代码中的age就是一个只读属性,如果将第20行代码前面的注释符取消,则系统会报错“AttributeError: can't set attribute”,即不能设置age属性的值。</p><p>对于有getter/setter方法的属性,只要对该属性赋值,就会执行setter方法;只要读取该属性的值,就会执行getter方法。例如,对于代码中的第17行和第21行代码,当给stu.score赋值时,都会自动执行第6至11行的代码。对于第19行和第22行代码,当读取stu.age的值时,会自动执行第12至14行的代码;当读取stu.score的值时,会自动执行第3至5行代码。</p><p>注意 在类的setter和getter方法中使用self访问属性时,需要在属性名前加上下划线,否则系统会因不断递归调用而报错。例如,第5行和第11行通过self访问score属性时都是用“self._score”(score前面有一个下划线)。</p><p><br ></p>
    王恺-南开大学 发表于2019年04月26日
    添加评论
  • 2楼

  • 王恺-南开大学 发表于2019年04月26日
    1 | 0 | 举报
    <p>补充一句,@property装饰器与函数中介绍的装饰器没有任何关系,完全不同的作用。</p>
    王恺-南开大学 发表于2019年04月26日
    添加评论