第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 返回一个值,则返回原 ...
随机推荐
- VSCode--HTML代码片段(基础版,react、vue、jquery)
起因是最近在学习前端,看的网上的demo也是在react.vue.jquery之间穿插,为了方便一键生成html模板(懒)写demo,有了以下折腾. 本人使用的前端编辑工具是vscode(方便.懒), ...
- GROUP BY 分组后得到最新即时间最大的一条数据(需添加limit才可生效)
当使用GROUP BY 分组,默认返回的数据是组中最小的记录即id最小的数据, 当开发中经常会需要分组后将最新的数据放在前面, 为了实现需求,使用了嵌套查询,分别使用order by来排序 SELEC ...
- day87:luffy:结算页面积分&支付宝接口
目录 1.积分 2.支付 1.积分 1.关于积分的表结构 1.在user表中添加credit字段 + 设计一个积分的表结构 user/models.py class User(AbstractUser ...
- php 检测敏感字
public function getMin($content){//调用接口 $content_url ="http://www.ju1.cn/index.php/Index/add.ht ...
- go get以后下载的包不在src下而在pkg的问题
我的GOPATH是这样的 但是当我go get下载包之后 下载的却不在src,而是在 $GOPATH$/pkg 下 原因可能是之前第一次go get下载, GitHub的速度太慢了,我更改了代理,使用 ...
- Java中的Socket用法
转发链接:https://www.cnblogs.com/zhanglei93/p/6217384.html (1)Java中的Socket用法 Java中的Socket分为普通的Socket和Nio ...
- [从源码学设计]蚂蚁金服SOFARegistry之程序基本架构
[从源码学设计]蚂蚁金服SOFARegistry之程序基本架构 0x00 摘要 之前我们通过三篇文章初步分析了 MetaServer 的基本架构,MetaServer 这三篇文章为我们接下来的工作做了 ...
- NO.A.0010——Windows常用快捷键使用教程
小娜操作: Win + C: 打开Cortana微软小娜,并开始聆听...... Win + Q: 打开Cortana: Win + S: 打开Cortana:sdfghjkrtgyh XBOX操作: ...
- [大雾雾雾雾] 告别该死的 EFCore Fluent API (续)
朋友们好啊, 我是 .NET 打工人 玩双截棍的熊猫 刚才有个朋友问我 猫猫发生什么事了 我说 怎么回事? 给我发了一张截图 我一看!嗷!原来是zuo天有两个数据库, 一个四十多岁,一个三十多岁 它们 ...
- 20-SAP PI开发手册-ERP发布服务供外部系统调用(sproxy代理类)
一. 接口内容 接口详细信息 1. 字段对应关系 发送字段对应关系 返回字段对应关系 2. 报文信息 传入报文(报文结构,外围系统提供) 1 <?xml version=" ...