轻松理解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编写暴力破解FTP密码小工具
Nov 19 Python
Python 的内置字符串方法小结
Mar 15 Python
python获取list下标及其值的简单方法
Sep 12 Python
Python使用爬虫爬取静态网页图片的方法详解
Jun 05 Python
Python图像处理之gif动态图的解析与合成操作详解
Dec 30 Python
Python Datetime模块和Calendar模块用法实例分析
Apr 15 Python
Python中的十大图像处理工具(小结)
Jun 10 Python
django echarts饼图数据动态加载的实例
Aug 12 Python
python实现视频读取和转化图片
Dec 10 Python
Tensorflow轻松实现XOR运算的方式
Feb 03 Python
Python发送手机动态验证码代码实例
Feb 28 Python
python实现PDF中表格转化为Excel的方法
Jun 16 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
mysql4.1以上版本连接时出现Client does not support authentication protocol问题解决办法
2007/03/15 PHP
用PHP读取RSS feed的代码
2008/08/01 PHP
php中将汉字转换成拼音的函数代码
2012/09/08 PHP
Yii2.0中的COOKIE和SESSION用法
2016/08/12 PHP
PHP入门教程之表单与验证实例详解
2016/09/11 PHP
一些常用的JS功能函数(2009-06-04更新)
2009/06/04 Javascript
C#中TrimStart,TrimEnd,Trim在javascript上的实现
2011/01/17 Javascript
jquery 扑捉回车键事件代码
2014/04/24 Javascript
javascript中sort() 方法使用详解
2015/08/30 Javascript
浅析JS运动
2015/12/28 Javascript
jQuery leonaScroll 1.1 自定义滚动条插件(推荐)
2016/09/17 Javascript
jQuery中Find选择器用法示例
2016/09/21 Javascript
Node.js 利用cheerio制作简单的网页爬虫示例
2018/03/01 Javascript
jQuery.extend 与 jQuery.fn.extend的用法及区别实例分析
2018/07/25 jQuery
微信小程序wepy框架学习和使用心得详解
2019/05/24 Javascript
跟老齐学Python之使用Python操作数据库(1)
2014/11/25 Python
用于统计项目中代码总行数的Python脚本分享
2015/04/21 Python
利用python实现命令行有道词典的方法示例
2017/01/31 Python
python3.X 抓取火车票信息【修正版】
2018/06/19 Python
python贪吃蛇游戏代码
2020/04/18 Python
基于python traceback实现异常的获取与处理
2019/12/13 Python
Python如何读取、写入CSV数据
2020/07/28 Python
HTML5混合开发二维码扫描以及调用本地摄像头
2017/12/27 HTML / CSS
美国社交购物市场:MassGenie
2019/02/18 全球购物
最新大学生自我评价
2013/09/24 职场文书
护理专业毕业生自荐信范文
2014/01/05 职场文书
学习决心书
2014/03/11 职场文书
市场调研项目授权委托书范本
2014/10/04 职场文书
个人存款证明书
2014/10/18 职场文书
出差报告范文
2014/11/06 职场文书
家长高考寄语
2015/02/27 职场文书
巴黎圣母院观后感
2015/06/10 职场文书
2016年少先队活动总结
2016/04/06 职场文书
500字作文之难忘的同学
2019/12/20 职场文书
Windows 11要来了?微软文档揭示Win11太阳谷 / Win10有两个不同版本
2021/11/21 数码科技
JS前端可视化canvas动画原理及其推导实现
2022/08/05 Javascript