位置: 编程技术 - 正文

Python中属性和描述符的正确使用(python特性和属性)

编辑:rootadmin

推荐整理分享Python中属性和描述符的正确使用(python特性和属性),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:python中的属性和方法,python属性值,python特性和属性,python 属性,简述python中属性与方法,python属性函数,python属性值,python属性描述符,内容如对您有帮助,希望把文章链接给更多的朋友!

关于@property装饰器

在Python中我们使用@property装饰器来把对函数的调用伪装成对属性的访问。

那么为什么要这样做呢?因为@property让我们将自定义的代码同变量的访问/设定联系在了一起,同时为你的类保持一个简单的访问属性的接口。

举个栗子,假如我们有一个需要表示电影的类:

你开始在项目的其他地方使用这个类,但是之后你意识到:如果不小心给电影打了负分怎么办?你觉得这是错误的行为,希望Movie类可以阻止这个错误。 你首先想到的办法是将Movie类修改为这样:

但这行不通。因为其他部分的代码都是直接通过Movie.score来赋值的。这个新修改的类只会在__init__方法中捕获错误的数据,但对于已经存在的类实例就无能为力了。如果有人试着运行m.scrore= -,那么谁也没法阻止。那该怎么办?

Python的property解决了这个问题。

我们可以这样做

这样在任何地方修改score都会检测它是否小于0。

property的不足

对property来说,最大的缺点就是它们不能重复使用。举个例子,假设你想为ticket字段也添加非负检查。

下面是修改过的新类:

可以看到代码增加了不少,但重复的逻辑也出现了不少。虽然property可以让类从外部看起来接口整洁漂亮,但是却做不到内部同样整洁漂亮。

描述符登场

什么是描述符?

一般来说,描述符是一个具有绑定行为的对象属性,其属性的访问被描述符协议方法覆写。这些方法是__get__() 、 __set__()和__delete__() ,一个对象中只要包含了这三个方法中的至少一个就称它为描述符。

描述符有什么作用?

The default behavior for attribute access is to get, set, or delete the attribute from an object's dictionary. For instance, a.x has a lookup chain starting witha.__dict__[‘x'], then type(a).__dict__[‘x'], and continuing through the base classes of type(a) excluding metaclasses. If the looked-up value is an object defining one of the descriptor methods, then Python may override the default behavior and invoke the descriptor method instead. Where this occurs in the precedence chain depends on which descriptor methods were defined.—?摘自官方文档

简单的说描述符会改变一个属性的基本的获取、设置和删除方式。

先看如何用描述符来解决上面 property逻辑重复的问题。

Python中属性和描述符的正确使用(python特性和属性)

因为描述符优先级高并且会改变默认的get、set行为,这样一来,当我们访问或者设置Movie().score的时候都会受到描述符Integer的限制。

不过我们也总不能用下面这样的方式来创建实例。

这样太生硬了,所以我们还缺一个构造函数。

这样在获取、设置和删除score和ticket的时候都会进入Integer的__get__ 、 __set__ ,从而减少了重复的逻辑。

现在虽然问题得到了解决,但是你可能会好奇这个描述符到底是如何工作的。具体来说,在__init__函数里访问的是自己的self.score和self.ticket,怎么和类属性score和ticket关联起来的?

描述符如何工作

看官方的说明

If an object defines both __get__() and __set__(), it is considered a data descriptor. Descriptors that only define __get__() are called non-data descriptors (they are typically used for methods but other uses are possible).

Data and non-data descriptors differ in how overrides are calculated with respect to entries in an instance's dictionary. If an instance's dictionary has an entry with the same name as a data descriptor, the data descriptor takes precedence. If an instance's dictionary has an entry with the same name as a non-data descriptor, the dictionary entry takes precedence.

The important points to remember are:

descriptors are invoked by the __getattribute__() methodoverriding __getattribute__() prevents automatic descriptor callsobject.__getattribute__() and type.__getattribute__() make different calls to __get__().data descriptors always override instance dictionaries.non-data descriptors may be overridden by instance dictionaries.

类调用__getattribute__()的时候大概是下面这样子:

下面是摘自国外一篇博客上的内容。

Given a Class “C” and an Instance “c” where “c = C(…)”, calling “c.name” means looking up an Attribute “name” on the Instance “c” like this:

Get the Class from InstanceCall the Class's special method getattribute__. All objects have a default __getattributeInside getattribute

Get the Class's mro as ClassParentsFor each ClassParent in ClassParentsIf the Attribute is in the ClassParent's dictIf is a data descriptorReturn the result from calling the data descriptor's special method __get__()Break the for each (do not continue searching the same Attribute any further)If the Attribute is in Instance's dictReturn the value as it is (even if the value is a data descriptor)For each ClassParent in ClassParentsIf the Attribute is in the ClassParent's dictIf is a non-data descriptorReturn the result from calling the non-data descriptor's special method __get__()If it is NOT a descriptorReturn the valueIf Class has the special method getattrReturn the result from calling the Class's special method__getattr__.

我对上面的理解是,访问一个实例的属性的时候是先遍历它和它的父类,寻找它们的__dict__里是否有同名的data descriptor如果有,就用这个data descriptor代理该属性,如果没有再寻找该实例自身的__dict__ ,如果有就返回。任然没有再查找它和它父类里的non-data descriptor,最后查找是否有__getattr__

描述符的应用场景

python的property、classmethod修饰器本身也是一个描述符,甚至普通的函数也是描述符(non-data discriptor)

django model和SQLAlchemy里也有描述符的应用

总结

只有当确实需要在访问属性的时候完成一些额外的处理任务时,才应该使用property。不然代码反而会变得更加??拢??艺庋?崛贸绦虮渎?芏唷R陨暇褪潜疚牡娜?磕谌荩?捎诟鋈四芰τ邢蓿?闹腥缬斜饰蟆⒙呒?砦笊踔粮拍钚源砦螅?骨胩岢霾⒅刚??/p>

巧用python和libnmapd,提取Nmap扫描结果 每当我进行内网渗透面对大量主机和服务时,我总是习惯使用自动化的方式从nmap扫描结果中提取信息。这样有利于自动化检测不同类型的服务,例如对w

利用Python自动监控网站并发送邮件告警的方法 前言因为有一些网站需要每日检查是否有问题,所以需要一个报警监控的机制,这个需要你指定你发送的邮箱和你接收的邮箱,就可以做到对网站自动

简单谈谈python中的Queue与多进程 最近接触一个项目,要在多个虚拟机中运行任务,参考别人之前项目的代码,采用了多进程来处理,于是上网查了查python中的多进程一、先说说Queue(队

标签: python特性和属性

本文链接地址:https://www.jiuchutong.com/biancheng/386191.html 转载请保留说明!

上一篇:Python实现基本线性数据结构(用python绘制一条直线)

下一篇:巧用python和libnmapd,提取Nmap扫描结果(python libnum)

  • 代销商品的手续费税率是多少
  • 安装服务费增值税专票税率多少
  • 清税证明是什么要钱吗
  • 对公账户余额和实际不符
  • 返岗补贴怎么办理
  • 综合收益什么时候结算
  • 月末调整银行外币汇率会计分录
  • 跨区预缴增值税怎么做账
  • 加计抵扣进项税额会计分录
  • 房产开发后自用需要交土地增值税吗
  • 融资租赁营改增时间
  • 一般纳税人财务报表月报还是季报
  • 车间员工的质量管理制度
  • 预付账款发票到货未到怎么做账
  • 2月的发票入在1月可以吗
  • 个人去税局开劳务费需要注意什么
  • 如何界定广告
  • 土地使用税源编明细表怎么填
  • 免抵退税的范围
  • 信息技术包括哪几个方面
  • ios14 举报短信
  • 会计监督作用
  • 笔记本电脑按键掉了怎么修
  • 职业病治疗费用由谁来承担
  • 代发工资跨行手续怎么办
  • 电脑开不了机一直重启
  • 接受捐赠的增值税要交企业所得税吗
  • pdf在线预览备注
  • Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]
  • 原生js操作数组的方法
  • 营销策划费会计分录
  • mysql入门很简单
  • 增值税发票的规范
  • 教育培训学校是什么意思
  • 企业所得税核定管理办法
  • 其他应付款包括应付股利和应付利息吗
  • 期权分为哪几种
  • 公允价值进行会计计量
  • 销售自己使用过的物品免税吗
  • 免税所得包括哪些
  • 营改增之后建筑业预收账款是否需要预交税款
  • 所得税 补税
  • 企业专利权拥有人是指
  • 高铁票可以抵扣的进项
  • 年应税销售额是指纳税人在连续不超过12个月或四个季度
  • 话费报销属于什么费用
  • 收到公益性捐赠计入什么科目
  • 税收返还会计核算
  • 小规模纳税人不超过10万免增值税
  • 普票丢失可以以照片入账么
  • 公司日常费用支出表怎么做
  • 收据可不可以做账
  • mysql rand整数
  • windows进程数
  • windows xp开机按f12是什么操作
  • Mail.app增强插件:Universal Mailer介绍
  • centos inode
  • win1020h2版好不好
  • win10mobile下载官网
  • mac新建窗口快捷键
  • centos7打开命令行
  • centos7安装软件包命令
  • window10稳定版
  • Win7开机黑屏只有鼠标,进入安全模式也是黑屏
  • linux内核配置文件
  • 查找重复字符串
  • js中密码由字母和数字组成,长度为4-20
  • node.js安装模式选择
  • linux 删除inode
  • android 多个权限合并 弹窗
  • python和微信交互
  • jquery删除数据
  • Material Design:利用RecyclerView CardView实现新闻卡片样式
  • 小规模纳税人销售额怎么算
  • 如何理解改革创新是时代要求
  • 税务核查主要核算内容
  • 什么是企业融资,什么是政府融资
  • 加油发票如何抵扣
  • 金三系统企业所得税如何变更所得税缴纳方式?
  • 18个税种征税范围
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设