在创建实例属性时,如果直接把实例属性暴露出去,虽然写起来简单,但是存在一些风险,比如实例属性可以在外部被修改。

为了限制外部操作,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,在这些方法中还可以增加一些检查操作,比如在get_score中增加获取权限操作,在set_score中增加输入检查操作。

class Student(object):

    def __init__(self):
self._score = 60 def get_score(self):
print(self._score)
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 if __name__ == "__main__":
s = Student()
s.get_score()
s.set_score("aaa") # 语法报错

现在,对任意的Student实例进行操作,就不能随心所欲地设置score了。但是,上面的调用方法又略显复杂,没有直接调用属性这么直接简单。

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

方法一:使用@property装饰器

@property装饰器可以把一个类方法以获取属性的方式进行调用。@property装饰器只能获取值,如果要进行赋值或删除操作,就要使用到伴生装饰器@XXX.setter和@XXX.deleter(XXX为@property装饰的方法名称)

被@XXX.setter装饰的方法在赋值时被调用

被@XXX.deleter装饰的方法在对象被删除时被调用

class Student(object):

    def __init__(self):
self._score = 60 @property # 取值操作
def score(self):
print("@property被调用")
return self._score @score.setter # 赋值操作
def score(self, value): # 赋予的值传给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
print("@score.setter被调用") @score.deleter # 删除操作
def score(self):
self._score = 0
print("@score.deleter被调用") if __name__ == "__main__":
s = Student()
s.score # 当获取属性值时执行@property
s.score = 99 # 当赋值属性值时执行 @**.setter
del s.score # 当删除属性值时执行 @**.deleter

执行结果为:

方法二:使用property()创建类属性

第二种方式看起来与使用@property装饰器之前的方式相差不大,唯一不同的是使用了property()方法创建了一个类属性

class Student(object):

    def __init__(self):
self._score = 60 def get_score(self):
print(self._score)
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
print(f"修改score为{self._score}") def del_score(self):
self._score = 0
print("删除score") score = property(get_score, set_score, del_score) if __name__ == "__main__":
s = Student()
s.score # 当获取属性值时,执行property()的第一个方法
s.score = 99 # 当赋值属性值时,执行property()的第二个方法
del s.score # 当删除属性值时执行,执行property()的第三个方法。注意:实际项目中很少用该方法。

上面两种方法最终实现的效果是一样的,也没有使用限制,喜欢用哪种就用哪种!

Python 利用@property装饰器和property()方法将一个方法变成属性调用的更多相关文章

  1. @property装饰器和property()函数

    @property装饰器 Python内置的@property装饰器可以把类的方法伪装成属性调用的方式.也就是本来是Foo.func()的调用方法,变成Foo.func的方式. class Peopl ...

  2. python之内置装饰器(property/staticmethod/classmethod)

    python内置了property.staticmethod.classmethod三个装饰器,有时候我们也会用到,这里简单说明下 1.property 作用:顾名思义把函数装饰成属性 一般我们调用类 ...

  3. python staticmethod,classmethod方法的使用和区别以及property装饰器的作用

    class Kls(object): def __init__(self, data): self.data = data def printd(self): print(self.data) @st ...

  4. 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解

    第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一.    引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...

  5. 【python】@property装饰器

    Python内置的@property装饰器可以把类的方法伪装成属性调用的方式.也就是本来是Foo.func()的调用方法,变成Foo.func的方式.在很多场合下,这是一种非常有用的机制. class ...

  6. 面向对象之组合、封装、多态、property装饰器

    概要: 组合 封装 property装饰器 多态 Python推崇鸭子类型:解耦合,统一标准(不用继承) 1. 组合 继承:会传递给子类强制属性 组合:解耦合,减少占用内存.如:正常继承,如果一个班级 ...

  7. 三分钟搞定Python中的装饰器

    python的装饰器是python的特色高级功能之一,言简意赅得说,其作用是在不改变其原有函数和类的定义的基础上,给他们增添新的功能. 装饰器存在的意义是什么呢?我们知道,在python中函数可以调用 ...

  8. 第7.27节 Python案例详解: @property装饰器定义属性访问方法getter、setter、deleter

    上节详细介绍了利用@property装饰器定义属性的语法,本节通过具体案例来进一步说明. 一.    案例说明 本节的案例是定义Rectangle(长方形)类,为了说明问题,除构造函数外,其他方法都只 ...

  9. [转载]Python使用@property装饰器--getter和setter方法变成属性

    原贴:为什么Python不需要getter和setter getter 和 setter在java中被广泛使用.一个好的java编程准则为:将所有属性设置为私有的,同时为属性写getter和sette ...

随机推荐

  1. sql优化的8种方式 (下)

    五.条件列表值如果连续使用between替代in        六.无重复记录的结果集使用union all合并 MySQL数据库中使用union或union all运算符将一个或多个列数相同的查询结 ...

  2. feignclient发送get请求,传递参数为对象

    feignclient发送get请求,传递参数为对象.此时不能使用在地址栏传递参数的方式,需要将参数放到请求体中. 第一步: 修改application.yml中配置feign发送请求使用apache ...

  3. JS - 字符串转换成数组,数组转换成字符串

    1.字符串转换成数组: var arr = "1, 2, 3, 4, 5, 6"; arr.split(","); // ["1",&quo ...

  4. 【C/C++】最长无重复子数组

    题目描述 给定一个数组arr,返回arr的最长无重复元素子数组的长度,无重复指的是所有数字都不相同. 子数组是连续的,比如[1,2,3,4,5]的子数组有[1,2],[2,3,4]等等,但是[1,3, ...

  5. 【C/C++】C++ warning: control reaches end of non-void function return

    控制到达非void函数的结尾. 一些本应带有返回值的函内数到容达结尾后可能并没有返回任何值. 这时候,最好检查一下是否每个控制流都会有返回值. 我是ostream声明的时候没有写return out; ...

  6. Jenkins检测Maven项目是否引用快照包

    目录 一.简介 二.具体 一.简介 生产环境不允许使用快照包,但人为规定终究不如脚本进行检测,所以在打war包,检测是否引用了快照包,如果引用了宣布打包失败 二.具体 1.在pipeline的scri ...

  7. <转>单机版搭建Hadoop环境

    安装过程: 一.安装Linux操作系统 二.在Ubuntu下创建hadoop用户组和用户 三.在Ubuntu下安装JDK 四.修改机器名 五.安装ssh服务 六.建立ssh无密码登录本机 七.安装ha ...

  8. Python小组作业:基于yolov5的口罩佩戴识别

    Python老师给了三个小组项目:1.自身专业问题 2.人工智能 3.游戏或者小工具 提前告知了,写游戏不好拿高分,小工具又不能展示自己的水平.大一刚来也没碰到什么专业问题,于是经过讨论,决定了做人工 ...

  9. BUGKU web刷题记录

    web1 直接F12查看源码,得到flag. web2 直接输入验证码答案,长度被限制,修改可输入长度,提交后得到flag. web3 $what=$_GET['what']; echo $what; ...

  10. linux服务器加入AD域(sssd)~ 通过域用户ssh登录加域的linux服务器

    搭建域控:参考 https://www.cnblogs.com/taosiyu/p/12009120.html 域控计算机全名: WIN-3PLKM2PLE6E.zhihu.test.com 域:zh ...