轻松理解Python 中的 descriptor


Posted in Python onSeptember 15, 2017

定义

通常,一个 descriptor 是具有“绑定行为”的对象属性。所绑定行为可通过 descriptor 协议被自定义的 __get__() , __set__() 和 __delete__() 方法重写。如果一个对象的上述三个方法任意一个被重写,则就可被称为 descriptor。

属性的默认操作是从对象字典中获取、设置和删除一个属性。例如,a.x 有一个查找链,先 a.__dict__['x'] ,若没有则 type(a).__dict__['x'] ,若没有增往上查找父类直到元类。如果查找链中,对象被定义了 descriptor 方法,Python 就会覆盖默认行为。

Descriptor 是一个强大的工具,虽然开发者不常接触到它,但它其实就是类、属性、函数、方法、静态方法、类方法以及 super() 背后的运行机制。

Descriptor 协议

三个方法原型如下所示:

descr.__get__(self, obj, type=None) --> value
descr.__set__(self, obj, value) --> None
descr.__delete__(self, obj) --> None

数据 descriptor 是同时具有 __get__() 和 __set__() 方法的对象,若只有 __get__() 方法,则为非数据 descriptor。如果实例字典中有和数据 descriptor 同名的入口,则数据 descriptor 优先级更高。相反,非数据 descriptor 优先级低。

让 __set__() 方法抛出异常,就能创建一个只读数据 descriptor。

调用 descriptor

descriptor 可以直接通过方法名调用。例如, d.__get__(obj) 。

而通过访问对象属性,自动调用 descriptor 才是更通用的做法。例如,如果 d 定义了方法 __get__() ,则 obj.d 会调用 d.__get__(obj) 。

对于对象, b.x 会被转换成 type(b).__dict__['x'].__get__(b, type(b)) 。而对于类(是的,类也可以调用), B.x 会被转换成 B.__dict__['x'].__get__(None, B) 。

Descriptor 例子

class RevealAccess(object):
  """A data descriptor that sets and returns values
    normally and prints a message logging their access.
  """
  def __init__(self, initval=None, name='var'):
    self.val = initval
    self.name = name
  def __get__(self, obj, objtype):
    print('Retrieving', self.name)
    return self.val
  def __set__(self, obj, val):
    print('Updating', self.name)
    self.val = val
>>> class MyClass(object):
...   x = RevealAccess(10, 'var "x"')
...   y = 5
...
>>> m = MyClass()
>>> m.x
Retrieving var "x"
10
>>> m.x = 20
Updating var "x"
>>> m.x
Retrieving var "x"
20
>>> m.y
5

总结

以上所述是小编给大家介绍的Python 中的 descriptor,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python函数嵌套实例
Sep 23 Python
python登录豆瓣并发帖的方法
Jul 08 Python
Python selenium文件上传方法汇总
Nov 19 Python
回调函数的意义以及python实现实例
Jun 20 Python
关于django 数据库迁移(migrate)应该知道的一些事
May 27 Python
tensorflow 加载部分变量的实例讲解
Jul 27 Python
Django之提交表单与前后端交互的方法
Jul 19 Python
使用python将最新的测试报告以附件的形式发到指定邮箱
Sep 20 Python
解决python-docx打包之后找不到default.docx的问题
Feb 13 Python
keras处理欠拟合和过拟合的实例讲解
May 25 Python
在Python中如何使用yield
Jun 07 Python
Python作用域和名称空间的详细介绍
Apr 13 Python
Python 实现购物商城,含有用户入口和商家入口的示例
Sep 15 #Python
python中reload(module)的用法示例详解
Sep 15 #Python
Python 关于反射和类的特殊成员方法
Sep 14 #Python
在Python中执行系统命令的方法示例详解
Sep 14 #Python
关于Python如何避免循环导入问题详解
Sep 14 #Python
Python实现随机选择元素功能
Sep 14 #Python
python自动化脚本安装指定版本python环境详解
Sep 14 #Python
You might like
ThinkPHP3.2.2的插件控制器功能简述
2014/07/09 PHP
PHP使用NuSOAP调用Web服务的方法
2015/07/18 PHP
PHP自动载入类文件函数__autoload的使用方法
2019/03/25 PHP
PHP中mysqli_get_server_version()的实例用法
2020/02/03 PHP
用javascript自动显示最后更新时间
2007/03/15 Javascript
JavaScript动态调整TextArea高度的代码
2010/12/28 Javascript
javascript中字符串的定义示例代码
2013/12/19 Javascript
JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)
2014/08/16 Javascript
学习JavaScript设计模式(接口)
2015/11/26 Javascript
Javascript自定义事件详解
2017/01/13 Javascript
详解基于Vue+Koa的pm2配置
2017/10/24 Javascript
详解plotly.js 绘图库入门使用教程
2018/02/23 Javascript
JavaScript使用math.js进行精确计算操作示例
2018/06/19 Javascript
JavaScript引用类型Array实例分析
2018/07/24 Javascript
jquery实现轮播图特效
2020/04/12 jQuery
ant design pro中可控的筛选和排序实例
2020/11/17 Javascript
[01:08:44]NB vs VP 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python用imghdr模块识别图片格式实例解析
2018/01/11 Python
Python实现的圆形绘制(画圆)示例
2018/01/31 Python
Python matplotlib绘图可视化知识点整理(小结)
2018/03/16 Python
使用Python实现一个栈判断括号是否平衡
2018/08/23 Python
python实现nao机器人身体躯干和腿部动作操作
2019/04/29 Python
python通过安装itchat包实现微信自动回复收到的春节祝福
2020/01/19 Python
python怎么判断模块安装完成
2020/06/19 Python
Python在字符串中处理html和xml的方法
2020/07/31 Python
Python本地及虚拟解释器配置过程解析
2020/10/13 Python
英国排名第一的在线宠物用品商店:Monster Pet Supplies
2018/05/20 全球购物
使用useBean标志初始化BEAN时如何接受初始化参数
2012/02/11 面试题
公积金转移接收函
2014/01/11 职场文书
师范毕业生自我鉴定
2014/01/15 职场文书
入党自荐书范文
2014/03/09 职场文书
投标服务承诺书
2014/05/28 职场文书
2014国庆65周年领导讲话稿(3篇)
2014/09/21 职场文书
新闻稿怎么写
2015/07/18 职场文书
SQLServer中JSON文档型数据的查询问题解决
2021/06/27 SQL Server
SpringBoot2零基础到精通之数据与页面响应
2022/03/22 Java/Android