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

s = Student()
s.score = 9999

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

class Student(object):def get_score(self):return self._scoredef 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

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

>>> s = Student()
>>> s.set_score(60) # ok!
>>> s.get_score()
60
>>> s.set_score(9999)
Traceback (most recent call last):...
ValueError: score must between 0 ~ 100!

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

有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?对于追求完美的Python程序员来说,这是必须要做到的!

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

class Student(object):@propertydef score(self):return self._score@score.setterdef 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

@property的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:

>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):...
ValueError: score must between 0 ~ 100!

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

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

class Student(object):@propertydef birth(self):return self._birth@birth.setterdef birth(self, value):self._birth = value@propertydef age(self):return 2015 - self._birth

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

要特别注意:属性的方法名不要和实例变量重名。例如,以下的代码是错误的:

class Student(object):# 方法名称和实例变量均为birth:@propertydef birth(self):return self.birth

这是因为调用s.birth时,首先转换为方法调用,在执行return self.birth时,又视为访问self的属性,于是又转换为方法调用,造成无限递归,最终导致栈溢出报错RecursionError

小结

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

练习

请利用@property给一个Screen对象加上widthheight属性,以及一个只读属性resolution

# -*- coding: utf-8 -*-
# 测试:
s = Screen()
s.width = 1024
s.height = 768
print('resolution =', s.resolution)
if s.resolution == 786432:print('测试通过!')
else:print('测试失败!')

完整源码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-class Student(object):@propertydef score(self):return self._score@score.setterdef 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 = values = Student()
s.score = 60
print('s.score =', s.score)
# ValueError: score must between 0 ~ 100!
s.score = 9999

参考链接:

https://www.liaoxuefeng.com/wiki/1016959663602400/1017502538658208

Python 使用@property对属性进行数据规范性校验相关推荐

  1. python 中 property 属性的讲解及应用

    Python中property属性的功能是:property属性内部进行一系列的逻辑计算,最终将计算结果返回 property属性的有两种方式: 装饰器 即:在方法上应用装饰器 类属性 即:在类中定义 ...

  2. python创建类统计属性_轻松创建统计数据的Python包

    python创建类统计属性 介绍 (Introduction) Sometimes you may need a distribution figure for your slide or class ...

  3. Python使用property函数和使用@property装饰器定义属性访问方法的异同点分析

    Python使用property函数和使用@property装饰器都能定义属性的get.set及delete的访问方法,他们的相同点主要如下三点: 1.定义这些方法后,代码中对相关属性的访问实际上都会 ...

  4. Python使用property函数定义属性访问方法如果不定义fget会怎么样?

    我们知道Python使用property函数定义属性访问方法时的语法如下: 实例属性=property(fget=None, fset=None, fdel=None, doc=None) 而是要@p ...

  5. Python面向对象程序设计中属性的作用与用法

    公开的数据成员可以在外部随意访问和修改,很难保证用户进行修改时提供新数据的合法性,数据很容易被破坏,并且也不符合类的封装性要求.解决这一问题的常用方法是定义私有数据成员,然后设计公开的成员方法来提供对 ...

  6. python中property函数_python 邮件表格Python中property函数用法实例分析

    本文实例讲述了Python中property函数用法.分享给大家供大家参考,具体如下: 通常我们在访问和赋值属性的时候,都是在直接和类(实例的)的__dict__打交道,或者跟数据描述符等在打交道.但 ...

  7. 基于Python面向《海贼王》领域数据的知识图谱项目【100010385】

    <海贼王>知识图谱构建-项目报告 1. 项目背景 本次任务试图为<海贼王>中出现的各个实体,包括人物.地点.组织等,构建一个知识图谱,帮助我们更好的理解这部作品. 2. 项目内 ...

  8. python类的__slots__属性、__del__属性、上下文(__enter__和__exit__)、

    常规情况下,类的属性字典是共享的,而实例的字典是独立的.如果一个类的属性较少,但是拥有很多的实例,这些实例的属性字典会占用较多的内存空间.对这样的类来说,为了节省内存空间,可以使用__slots__类 ...

  9. df满足条件的值修改_文科生学 Python 系列 16:泰坦尼克数据 2(缺失值处理)

    第八课:案例分析 - 泰坦尼克数据 本节课将重点分析泰坦尼克号沉船事故,我们将探索是什么因素决定了最后是否生还. 我们将将前面课程所学过的知识点融会贯通,举一反三 新增知识点: 缺失值处理:panda ...

最新文章

  1. HDU-1789-Doing Homework again
  2. CEAC网络构建试题
  3. EF中DB First模式下数据库中表结构变化时如何快速同步到EF模型中
  4. 2021年B站创作者生态报告
  5. 20、查看帮助的命令--man,info,whatis,--help
  6. 当深度学习遇上图: 图神经网络的兴起!
  7. python决策树代码解读_建模分析之机器学习算法(附pythonR代码)
  8. 计算C(n,0)+C(n,1)+...+C(n,m)--Problem B. Harvest of Apples
  9. 有没有安卓4.0的java模拟器_电脑端安装Android4.0模拟器使用教程
  10. msvcp110d.dll 丢失问题原因及解决思路
  11. 传媒业进入B2C领域:香港商报推爱购商城
  12. 深圳市工信局、发改委与商务局项目
  13. 用beamoff给VMware的Mac OS X 10.10.x加速
  14. EMC测试项目——辐射骚扰
  15. 使用SCI-HUB下载论文
  16. Android—项目结构
  17. 微博如何快速批量取消关注脚本教程
  18. mysql中文显示标题列_我在数据库中建立的列名为英文的,但标题是中文的,在编程界面中显示的是英文的列名,怎样设置成中文的?...
  19. 哇哦,它让美味随心所“鲜”
  20. 《Swift4.0互动教程》正式发布

热门文章

  1. python源码精要(6)-CPython编译标志
  2. go语言基础到提高(3)-变量
  3. 【数据挖掘】谷歌提出最新时序框架--Deep Transformer
  4. 【GNN】啥是GNN?GNN咋学?GNN何用?
  5. 【深度学习】PyTorch 历史版本安装-祖传老代码运行刚需
  6. 【心路历程】你是这样的“夜间工程师”吗?
  7. 【论文解读】CIKM20-MiNet:阿里|跨域点击率预估混合兴趣模型
  8. 【论文导读】DLP-KDD2019|BST---使用Transformer进行序列推荐
  9. 【深度学习】9 大主题卷积神经网络(CNN)的 PyTorch 实现
  10. 【机器学习基础】数学推导+纯Python实现机器学习算法18:奇异值分解SVD