轻松理解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怎么学好python?
Oct 07 Python
理解Python中的With语句
Feb 02 Python
Python多线程编程(三):threading.Thread类的重要函数和方法
Apr 05 Python
Python实现批量将word转html并将html内容发布至网站的方法
Jul 14 Python
Python爬取qq music中的音乐url及批量下载
Mar 23 Python
如何用python整理附件
May 13 Python
python实现QQ邮箱/163邮箱的邮件发送
Jan 22 Python
python实现手机销售管理系统
Mar 19 Python
Python+OpenCV+pyQt5录制双目摄像头视频的实例
Jun 28 Python
python的列表List求均值和中位数实例
Mar 03 Python
python输入中文的实例方法
Sep 14 Python
聊聊pytorch测试的时候为何要加上model.eval()
May 23 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遍历数组的方法分享
2012/03/22 PHP
如何给phpcms v9增加类似于phpcms 2008中的关键词表
2013/07/01 PHP
PHP中CURL的CURLOPT_POSTFIELDS参数使用细节
2014/03/17 PHP
PHP正则表达式过滤html标签属性(DEMO)
2016/05/04 PHP
一个简单安全的PHP验证码类、PHP验证码
2016/09/24 PHP
javascript 当前日期转化为中文的实现代码
2010/05/13 Javascript
juqery 学习之三 选择器 子元素与表单
2010/11/25 Javascript
各情景下元素宽高的获取实现代码
2011/09/13 Javascript
jquery移动节点实例
2015/01/14 Javascript
jQuery控制网页打印指定区域的方法
2015/04/07 Javascript
js判断图片加载完成后获取图片实际宽高的方法
2016/02/25 Javascript
基于JavaScript实现跳转提示页面
2016/09/24 Javascript
vue bootstrap小例子一枚
2017/06/09 Javascript
vue使用vue-i18n实现国际化的实现代码
2018/04/08 Javascript
JavaScript new对象的四个过程实例浅析
2018/07/31 Javascript
JavaScript中Dom操作实例详解
2019/07/08 Javascript
angularjs1.X 重构controller 的方法小结
2019/08/15 Javascript
微信小程序自定义导航栏(模板化)
2019/11/15 Javascript
JavaScript canvas动画实现时钟效果
2020/02/10 Javascript
微信小程序实现加入购物车滑动轨迹
2020/11/18 Javascript
详解Vue3 Teleport 的实践及原理
2020/12/02 Vue.js
python批量下载图片的三种方法
2013/04/22 Python
Python用sndhdr模块识别音频格式详解
2018/01/11 Python
python3+PyQt5实现自定义分数滑块部件
2018/04/24 Python
Python格式化输出字符串方法小结【%与format】
2018/10/29 Python
python实现停车管理系统
2018/11/30 Python
解决启动django,浏览器显示“服务器拒绝访问”的问题
2020/05/13 Python
美国高品质个性化珠宝销售网站:Jewlr
2018/05/03 全球购物
C#笔试题
2015/07/14 面试题
二年级语文教学反思
2014/02/02 职场文书
2014年党员干部四风问题自我剖析材料
2014/09/29 职场文书
仰望星空观后感
2015/06/10 职场文书
解决pytorch-gpu 安装失败的记录
2021/05/24 Python
python必学知识之文件操作(建议收藏)
2021/05/30 Python
浅谈MySQL 亿级数据分页的优化
2021/06/15 MySQL
JavaScript实现贪吃蛇游戏
2021/06/16 Javascript