使用@property

在绑定属性时,如果直接把属性暴露出去,虽然写起来简单,但是没法检查参数,导致可以把成绩随便改:

>>> class Student(object):
pass >>> s =Student()
>>> s.score=999
>>> s.score
999

这显然不符合逻辑,为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:

>>> class Student(object):
def get_score(self):
return self.score
def set_score(self,value):
if not isinstance(value,int):
raise ValueError("score must be an integer")
if value <0 or value > 100:
raise ValueError("score must between 0~100")
self.score = value >>> s = Student()
>>> s.set_score('a') Traceback (most recent call last):
File "<pyshell#57>", line 1, in <module>
s.set_score('a')
File "<pyshell#54>", line 6, in set_score
raise ValueError("score must be an integer")
ValueError: score must be an integer
>>> s.set_score(99999) Traceback (most recent call last):
File "<pyshell#58>", line 1, in <module>
s.set_score(99999)
File "<pyshell#54>", line 8, in set_score
raise ValueError("score must between 0~100")
ValueError: score must between 0~100
>>> s.set_score(99)
>>> s.get_score()
99
>>>

现在,对任意的Student实例进行操作,就不能随心所欲地设置score了:

但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。

有没有技能检查参数,有可以用雷士属性这样简单地方式来访问类的变量?

记得装饰器(decorator)可以给函数动态加上功能?对于累的方法,装饰器一样起作用,Python内置的@property装饰器就是负责把一个方法变成属性调用的:

>>> class Student(object):

    @property
def score(self):
return self._score @score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value >>> s = Student()
>>> s.score =99
>>> s.score = 999 Traceback (most recent call last):
File "<pyshell#76>", line 1, in <module>
s.score = 999
File "<pyshell#73>", line 12, in score
raise ValueError('score must between 0 ~ 100!')
ValueError: score must between 0 ~ 100!
>>> s.score = 'a' Traceback (most recent call last):
File "<pyshell#77>", line 1, in <module>
s.score = 'a'
File "<pyshell#73>", line 10, in score
raise ValueError('score must be an integer!')
ValueError: score must be an integer!
>>>

注意这个@property,在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。

还可以定义只读属性,值定义getter方法,不定义setter方法就是一个只读属性:

>> class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self,value):
self._birth = value
@property
def age(self):
return 2017 - self._birth >>> s = Student()
>>> s.birth = 1995 >>> s.age
22
>>> s.age = 23 Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
s.age = 23
AttributeError: can't set attribute
>>>

上面的birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来。

总结

@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样程序运行时就减少了出错的可能性。

Python面向对象高级编程-@property的更多相关文章

  1. python面向对象高级编程

    正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性.先定义class: >>> class Studen ...

  2. Python面向对象高级编程:@property--把方法变为属性

    为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数: >>> ...

  3. python 面向对象高级编程

    数据封装.继承和多态只是面向对象程序设计中最基础的3个概念.在Python中,面向对象还有很多高级特性,允许我们写出非常强大的功能. 我们会讨论多重继承.定制类.元类等概念.

  4. python面向对象高级:@property

    @property 把方法『变成』了属性,广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性. 最大的作用就是既能检查参数,又可以用类 ...

  5. Python面向对象高级编程-__slots__、定制类,枚举

    当在类体内定义好各种属性后,外部是可以随便添加属性的,Python中类如何限制实例的属性? Python自带了很多定制类,诸如__slots__,__str__ __slots__ __slots__ ...

  6. Python面向对象高级编程:__slot__(给实例添加方法、属性)

    纲要: 本章总的来说是给实例添加属性,给类添加方法两个主题,以及相应的作用范围.总结如下: 1.给实例添加属性(作用范围:当然是只对当前实例有效): 2.用__slots__限制可以给实例添加的属性( ...

  7. Python面向对象高级编程-_slots_

    使用_slots_ 正常情况下,当定义一个class,创建一个class的实例后,可以给实例绑定任何属性和方法,这就是动态语言的灵活性.先定义class: >>> class Stu ...

  8. C++面向对象高级编程(九)Reference与重载operator new和operator delete

    摘要: 技术在于交流.沟通,转载请注明出处并保持作品的完整性. 一 Reference 引用:之前提及过,他的主要作用就是取别名,与指针很相似,实现也是基于指针. 1.引用必须有初值,且不能引用nul ...

  9. C++面向对象高级编程(八)模板

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 这节课主要讲模板的使用,之前我们谈到过函数模板与类模板 (C++面向对象高级编程(四)基础篇)这里不再说明 1.成员模板 成员模板:参数为tem ...

随机推荐

  1. mysql之mysql、mysql-devel、mysql-server

    一.引言 一直都没搞明白这三者之间的关系,于是决心查资料把这个问题搞明白,遂记录以便查阅.学习 二.关系 mysql-devel 开发用到的库以及包含文件mysql mysql 客户端mysql-se ...

  2. django中使用POST方法 使用ajax后出现“CSRF token missing or incorrect”

    这个是因为在django的ajax中默认添加了token,因此需要在cookie中增加token头信息. 首先使用JavaScript函数获取token: function getCookie(nam ...

  3. NetBeans 设置code completion/auto pop-up delay

    如果你在Tools>Options>Editor>Code Completion>Language: Java 没有找到设置delay的选项.那就去C盘(如果你用的是Windo ...

  4. hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙

    /** 题目:hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4106 ...

  5. Android.mk介绍

    Secrets of Android.mk Intro to Android.mk Simple example NDK Usage Defining Modules Simple APK APK D ...

  6. php 计算时间添加

    $Date_1=date("Y-m-d");$Date_2="2015-10-11";$d1=strtotime($Date_1);$d2=strtotime( ...

  7. CI 框架购物车问题

    因为CI 是外国的框架.购物逻辑和中国的不一样.所以需要改进ci 框架的 cart 类: (1)先把 cart类拷贝一份到application/libaries/下 (2)因为cart中购车中的商品 ...

  8. CodeSmith自动生成代码使用

    官网地址:http://www.codesmithtools.com/ CodeSmith开发系列资料总结 http://terrylee.cnblogs.com/archive/2005/12/28 ...

  9. 20140710文安c++面试总结

    这次去文安面试并未是我想象中的那个样子,可能有如下原因: 1.招聘旺季已过,仅剩下c++这个职位 2.并未做过面试前大公司的面试技巧-做面试题 面试过程基本就是先做面试题: 1.试题分布式-逻辑题.分 ...

  10. (转)Unity笔记之编辑器(BeginFadeGroup、BeginHorizontal、BeginScrollView) ... ...

    1. BeginFadeGroup(float value) 这是EditorGUILayout中的一个函数,用来隐藏/显示在它包含的组中的内容.value则是显示内容的量,范围是0-1 . 比较下未 ...