第7.23节 Python使用property函数定义属性简化属性访问的代码实现
第7.23节 Python使用property函数定义属性简化属性访问的代码实现
一、 背景
在本章前面章节中,我们介绍了类相关的知识,并举例进行了说明,在这些例子中会定义一些形如 “get属性”、“set属性”的实例属性的存取方法,当实例数据的属性是私有时,这些数据的访问都只能通过存取方法进行方法,而没有设置为私有的实例数据如果要遵循特定的规则可能也只能通过存取方法访问。但如果一个程序要访问比较多的实例的数据时,大量使用这种存取方法会让程序显得单调而冗长。为了解决该问题,Python提供了一种机制,可以象使用普通类实例变量访问那样访问这些属性,并能确保使用类定义的访问方法来进行相关访问,相当于类似于普通实例变量赋值、查询、删除的访问方法,但真正执行则依靠类定义的属性访问方法。这个就是使用property函数来定义实例属性进行访问。
二、 语法释义
1. 定义语法就是对于要定义的实例属性在类体代码中增加如下一行语句:
实例属性=property(fget=None, fset=None, fdel=None, doc=None)
例如在类Rectangle中定义了长方形的长的访问方法getLen,setLen,且长方形的长存储在一个实例变量length甚至是一个私有变量__length中,我们可以使用如下语句在类内定义一个新的实例属性来访问长方形的长:
len = property(getLen,setLen,None,'长方形的长')
2. 语法释义
1) 实例属性:是指以后要通过这种模式访问的属性名,该属性名必须使用新定义的实例属性,不能用原来已经定义的属性,以后相关数据的访问依靠该属性进行;需要特别说明的是,新定义的这个实例属性可以和一个或多个实例变量关联,具体关联是通过get和set方法去设置的,比如上面的例子,在类内应该有如下两个实例方法:
def setLen(self,length):self.__length=length
def getLen(self): return self.__length
2) 上面的方法定义实例属性的类型并不是哪个实例变量的属性,而是一个类型为”property”新对象,在其中会保存需要访问的真正实例变量对应操作的方法。property并不是一个真正的函数,它是一个拥有许多特殊方法的类,Property对象有三个方法,getter(), setter()和delete(),用来在对象创建后设置fget,fset和fdel方法。其本质是把调用属性访问的方法伪装成对新定义属性的访问。
3) property函数的四个参数:
a) 四个参数按顺序依次为get读取属性方法、set设置属性方法、del 删除属性方法和 doc,其中前三个参数对应三个实例方法分别进行某个或某些属性的读取、设置和删除, doc 是一个文档字符串,用于说明该新定义的属性,在这些方法里可以执行相关校验和数据处理变换,以保证数据访问的正确性;
b) 在实际使用时,调用 property 也可传入 0 个(既不能读,也不能写的属性)、1 个(只读属性)、2 个(读写属性)、3 个(读写属性,也可删除)和 4 个(读写属性,也可删除,包含文档说明)参数。
3. 定义了get、set、del方法去操作某个或某些实例变量,并用property函数进行这些方法和属性的操作绑定,则对应属性就等同于实例变量一样可以访问,访问时会自动调用相关的get、set、del方法。举例:
我们定义了一个长方形的类的实例:rect=Rectangle(5,4)后,可以通过:print(rect.len)输出长的信息,通过rect.len=10将其长度调整为10。实际上上述操作等同于:
print(rect.getLen())
rect.setLen(10)
上述例子是一个用定义的属性去访问一个私有属性,是一对一的,实际上定义属性可以和类原来定义的实例变量(含私有变量)进行一对多的访问,可以对定义的属性经过运算去改变多个实例变量,因为都是通过set方法去赋值,至于赋值给谁、怎么赋值是set方法来决定的。
4. 如果property定义属性对应的内部实例变量是外部可以访问的,对实例变量的访问是不会触发这些方法的。如果上述案例中self.__length(当然self.__length无法直接访问,但如果是self.length呢)可以从外部赋值,则是直接进行实例变量赋值,不会执行相关set方法。
三、 property函数来定义实例属性的优点
1. 使用property定义实例属性,把通过显示地调用诸如get、set类的方法访问实例变量改成了实例属性的使用和赋值,这样可以有效提高代码的可读性和简洁性,同时还能确保访问逻辑的正确;
2. 在特定场景下,如果历史代码中的实例变量使用直接访问方式使用,但由于业务要求,对该属性需要增加特定访问逻辑,按照常规实现方式需要将所有变量访问改成get、set方法,需要修改大量代码并进行大量测试,而使用property则可以轻松的解决个问题,它可以将原实例变量改名,加上相应的原实例变量需要增强访问逻辑控制的代码的访问方法,然后使用property定义成原实例变量的名字就可以简单实现上述要求。
本节对在类中使用property函数定义一个可供外部简便访问的实例属性的语法进行了说明和解释,需要注意的是这个新定义的属性的读写访问都会通过内部的方法进行,这样简化了属性访问特别是赋值和删除的方法,同时又保证了数据访问的逻辑。下节将结合详细的案例进行进一步介绍。
老猿Python(https://blog.csdn.net/LaoYuanPython)系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。
欢迎大家批评指正,谢谢大家关注!
第7.23节 Python使用property函数定义属性简化属性访问的代码实现的更多相关文章
- Python使用property函数定义的属性名与其他实例变量重名会怎么样?
首先如果定义的属性名与该属性对应的操作方法操作的实例对象同名就会触发无穷的递归调用,相关部分请参考<Python案例详解:使用property函数定义与实例变量同名的属性会怎样?> 但如果 ...
- Python使用property函数定义属性访问方法如果不定义fget会怎么样?
我们知道Python使用property函数定义属性访问方法时的语法如下: 实例属性=property(fget=None, fset=None, fdel=None, doc=None) 而是要@p ...
- Python使用property函数和使用@property装饰器定义属性访问方法的异同点分析
Python使用property函数和使用@property装饰器都能定义属性的get.set及delete的访问方法,他们的相同点主要如下三点: 1.定义这些方法后,代码中对相关属性的访问实际上都会 ...
- 第7.25节 Python案例详解:使用property函数定义与实例变量同名的属性会怎样?
第7.25节 Python案例详解:使用property函数定义与实例变量同名的属性会怎样? 一. 案例说明 我们上节提到了,使用property函数定义的属性不要与类内已经定义的普通实例变量重 ...
- 第7.24节 Python案例详解:使用property函数定义属性简化属性访问代码实现
第7.24节 Python案例详解:使用property函数定义属性简化属性访问代码实现 一. 案例说明 本节将通过一个案例介绍怎么使用property定义快捷的属性访问.案例中使用Rectan ...
- 第11.23节 Python 中re模块的搜索替换功能:sub及subn函数
一. 引言 在<第11.3节 Python正则表达式搜索支持函数search.match.fullmatch.findall.finditer>重点介绍了几个搜索函数,除了搜索,re模块也 ...
- 第11.15节 Python正则表达式转义符定义的特殊序列
一. 引言 在前面<第11.13节 Python正则表达式的转义符"\"功能介绍>介绍了正则表达式转义符'\',只不过当时作为转义符主要是用于在正则表达式中表示元字符自 ...
- python简单的函数定义和用法实例
python简单的函数定义和用法实例 这篇文章主要介绍了python简单的函数定义和用法,实例分析了Python自定义函数及其使用方法,具有一定参考借鉴价值,需要的朋友可以参考下 具体分析如下: 这里 ...
- python学习7—函数定义、参数、递归、作用域、匿名函数以及函数式编程
python学习7—函数定义.参数.递归.作用域.匿名函数以及函数式编程 1. 函数定义 def test(x) # discription y = 2 * x return y 返回一个值,则返回原 ...
随机推荐
- Manacher (马拉车) 算法:解决最长回文子串的利器
最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...
- 《精通Spring4.x企业应用开发实战》第三章
这一章节主要介绍SpringBoot的使用,也是学习的重点内容,之后就打算用SpringBoot来写后台,所以提前看一下还是很有必要的. 3.SpringBoot概况 3.1.1SpringBoot发 ...
- 咀嚼Lock和Synchronized锁
1.Synchronized锁 底层是monitor监视器,每一个对象再创建的时候都会常见一个monitor监视器,在使用synchronized代码块的时候,会在代码块的前后产生一个monitorE ...
- 主题包含一张index.html
有半年之久没有更新新作品了,但这个小小领地我并没有忘记,我会坚持下去,一直在这等你,等你的每次回眸,感恩你的每次驻足,这已经足够成为我坚守的动力和理由,尽管现在有很多不足和不尽人意,也没很多的时间管理 ...
- k8s event监控利器kube-eventer对接企微告警
背景 监控是保障系统稳定性的重要组成部分,在Kubernetes开源生态中,资源类的监控工具与组件监控百花齐放. cAdvisor:kubelet内置的cAdvisor,监控容器资源,如容器cpu.内 ...
- js匀速运动框架案例
点击"开始运动"按钮,红色的#red区块开始向右匀速运动,抵达到黑色竖线位置自动停止,再次点击"开始运动"#red区块也不会再运动.同时为了便于后期维护,要求运 ...
- Spring Boot 创建 Docker 镜像
随着越来越多的组织转向容器和虚拟服务器,Docker正成为软件开发工作流程中一个更重要的部分.为此,Spring Boot 2.3中最新的功能之中,提供了为Spring Boot应用程序创建 Dock ...
- 优测 x QTA 兼容性测试全面启动啦
鉴于Android系统开放性开发,以及Android系统在智能机市场的覆盖率超高的特点,APP的兼容性测试需求大幅提升.为迎合市场需求,优测(Utest)与QTA合作,全力打造兼容性测试服务.由优测提 ...
- python读取excel数据转换成字典
以上面的excel格式,输出字典类型: import xlrddef read_excel_data(): filename = 'E:\学历列表.xls' data = xlrd.open_work ...
- 如何统计Ceph的RBD真实使用容量
前言 ceph的rbd一直有个问题就是无法清楚的知道这个分配的空间里面到底使用了多少,这个在Jewel里面提供了一个新的接口去查询,对于老版本来说可能同样有这个需求,本篇将详细介绍如何解决这个问题 查 ...