轻松理解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实现简单多线程任务队列
Feb 27 Python
Python中的is和==比较两个对象的两种方法
Sep 06 Python
django rest framework之请求与响应(详解)
Nov 06 Python
Python语言生成水仙花数代码示例
Dec 18 Python
python使用opencv按一定间隔截取视频帧
Mar 06 Python
tensorflow实现softma识别MNIST
Mar 12 Python
使用Python监视指定目录下文件变更的方法
Oct 15 Python
python+opencv实现霍夫变换检测直线
Oct 23 Python
Django框架创建mysql连接与使用示例
Jul 29 Python
Python对称的二叉树多种思路实现方法
Feb 28 Python
用Python在Excel里画出蒙娜丽莎的方法示例
Apr 28 Python
基于python实现查询ip地址来源
Jun 02 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
理解php Hash函数,增强密码安全
2011/02/25 PHP
解析php时间戳与日期的转换
2013/06/06 PHP
非常好用的Zend Framework分页类
2014/06/25 PHP
PHP中提问频率最高的11个面试题和答案
2014/09/02 PHP
PHP实现找出链表中环的入口节点
2018/01/16 PHP
jQuery之ajax技术的详细介绍
2013/06/19 Javascript
JS将秒换成时分秒实现代码
2013/09/03 Javascript
了不起的node.js读书笔记之mongodb数据库交互
2014/12/22 Javascript
学习JavaScript正则表达式
2015/11/13 Javascript
JS运动相关知识点小结(附弹性运动示例)
2016/01/08 Javascript
Angularjs手动解析表达式($parse)
2016/10/12 Javascript
Angular2  NgModule 模块详解
2016/10/19 Javascript
基于JavaScript实现活动倒计时效果
2017/04/20 Javascript
jQuery ajax读取本地json文件的实例
2017/10/31 jQuery
深入解读Node.js中的koa源码
2019/06/17 Javascript
webpack HappyPack实战详解
2019/10/08 Javascript
vue+iview分页组件的封装
2020/11/17 Vue.js
详解pyqt5 动画在QThread线程中无法运行问题
2018/05/05 Python
Django 多语言教程的实现(i18n)
2018/07/07 Python
解决Python selenium get页面很慢时的问题
2019/01/30 Python
python处理大日志文件
2019/07/23 Python
Django为窗体加上防机器人的验证码功能过程解析
2019/08/14 Python
python selenium操作cookie的实现
2020/03/18 Python
Python性能分析工具py-spy原理用法解析
2020/07/27 Python
python 动态绘制爱心的示例
2020/09/27 Python
微软俄罗斯官方网站:Microsoft俄罗斯
2016/09/18 全球购物
世界上最好的足球商店:Unisport
2019/03/02 全球购物
解释一下ruby中的特殊方法与特殊类
2013/02/26 面试题
大学生会计职业生涯规划范文
2014/02/28 职场文书
企业党员一句话承诺
2014/05/30 职场文书
三月学雷锋活动总结
2014/06/26 职场文书
幼儿园小班个人工作总结
2015/02/12 职场文书
大学生旷课检讨书1000字
2015/02/19 职场文书
Python趣味挑战之给幼儿园弟弟生成1000道算术题
2021/05/28 Python
解决mysql的int型主键自增问题
2021/07/15 MySQL
python保存图片的四个常用方法
2022/02/28 Python