轻松理解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 相关文章推荐
使用pyecharts在jupyter notebook上绘图
Apr 23 Python
python扫描proxy并获取可用代理ip的实例
Aug 07 Python
Python实现简单网页图片抓取完整代码实例
Dec 15 Python
Python之多线程爬虫抓取网页图片的示例代码
Jan 10 Python
python实现雨滴下落到地面效果
Jun 21 Python
使用pytorch进行图像的顺序读取方法
Jul 27 Python
python处理multipart/form-data的请求方法
Dec 26 Python
使用python判断jpeg图片的完整性实例
Jun 10 Python
网易2016研发工程师编程题 奖学金(python)
Jun 19 Python
python 利用turtle库绘制笑脸和哭脸的例子
Nov 23 Python
Python中 Global和Nonlocal的用法详解
Jan 20 Python
使用keras实现孪生网络中的权值共享教程
Jun 11 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中flush()、ob_flush()、ob_end_flush()的区别介绍
2013/02/17 PHP
php使用正则表达式提取字符串中尖括号、小括号、中括号、大括号中的字符串
2020/04/05 PHP
PHP Opcache安装和配置方法介绍
2015/05/28 PHP
cakephp常见知识点汇总
2017/02/24 PHP
php实现session共享的实例方法
2019/09/19 PHP
js 巧妙去除数组中的重复项
2010/01/25 Javascript
把字符串按照特定的字母顺序进行排序的js代码
2014/01/28 Javascript
Js 正则表达式知识汇总
2014/12/02 Javascript
jquery简单实现图片切换效果的方法
2015/05/12 Javascript
详解javascript中的事件处理
2015/11/06 Javascript
JQuery+EasyUI轻松实现步骤条效果
2016/02/22 Javascript
JavaScript简单实现弹出拖拽窗口(二)
2016/06/17 Javascript
AngularJS 实现弹性盒子布局的方法
2016/08/30 Javascript
关于jQuery.ajax()的jsonp碰上post详解
2017/07/02 jQuery
underscore之Collections_动力节点Java学院整理
2017/07/10 Javascript
vue-resource拦截器设置头信息的实例
2017/10/27 Javascript
nodeJs实现基于连接池连接mysql的方法示例
2018/02/10 NodeJs
Angular 利用路由跳转到指定页面的指定位置方法
2018/08/31 Javascript
深入Node TCP模块的理解
2019/03/13 Javascript
layer弹窗在键盘按回车将反复刷新的实现方法
2019/09/25 Javascript
jQuery冲突问题解决方法
2021/01/19 jQuery
[01:08:33]OG vs VGJ.T 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
对python判断ip是否可达的实例详解
2019/01/31 Python
djano一对一、多对多、分页实例代码
2019/08/16 Python
用 Django 开发一个 Python Web API的方法步骤
2020/12/03 Python
Farfetch香港官网:汇集全球时尚奢侈品购物平台
2017/11/26 全球购物
个性大学生自我评价
2013/12/04 职场文书
毕业生的自我评价范文
2013/12/31 职场文书
三八节标语
2014/06/27 职场文书
商业企业管理专业求职信
2014/07/10 职场文书
中韩经贸翻译专业大学生职业生涯规划范文
2014/09/18 职场文书
统计员岗位职责范本
2015/04/14 职场文书
2015年社区环境卫生工作总结
2015/04/21 职场文书
2015年物业公司保洁工作总结
2015/10/22 职场文书
python通配符之glob模块的使用详解
2021/04/24 Python
SQL Server代理:理解SQL代理错误日志处理方法
2021/06/30 SQL Server