轻松理解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中的yield使用方法
Feb 11 Python
部署Python的框架下的web app的详细教程
Apr 30 Python
Python解析nginx日志文件
May 11 Python
Python的条件语句与运算符优先级详解
Oct 13 Python
python中pandas.DataFrame的简单操作方法(创建、索引、增添与删除)
Mar 12 Python
python 列表,数组,矩阵两两转换tolist()的实例
Apr 04 Python
python退出命令是什么?详解python退出方法
Dec 10 Python
Python列表(list)所有元素的同一操作解析
Aug 01 Python
Python Django框架防御CSRF攻击的方法分析
Oct 18 Python
Python如何在DataFrame增加数值
Feb 14 Python
Flask-SocketIO服务端安装及使用代码示例
Nov 26 Python
Python自动化实战之接口请求的实现
May 30 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 彩色文字实现代码
2009/06/29 PHP
利用PHP生成静态HTML文档的原理
2012/10/29 PHP
PHP Directory 函数的详解
2013/03/07 PHP
基于PHP创建Cookie数组的详解
2013/07/03 PHP
PHP解压tar.gz格式文件的方法
2016/02/14 PHP
Symfony2实现在controller中获取url的方法
2016/03/18 PHP
php抽象方法和抽象类实例分析
2016/12/07 PHP
浅析jquery的作用与优势
2013/12/02 Javascript
js调用打印机打印网页字体总是缩小一号的解决方法
2014/01/24 Javascript
jquery.map()方法的使用详解
2015/07/09 Javascript
javascript实现动态统计图开发实例
2015/11/21 Javascript
AngularJS基础 ng-open 指令简单实例
2016/08/02 Javascript
KnockoutJS 3.X API 第四章之事件event绑定
2016/10/10 Javascript
原生js实现淘宝购物车功能
2020/06/23 Javascript
nuxt.js写项目时增加错误提示页面操作
2020/11/05 Javascript
Python3使用requests登录人人影视网站的方法
2016/05/11 Python
Python中使用bidict模块双向字典结构的奇技淫巧
2016/07/12 Python
Python数据分析中Groupby用法之通过字典或Series进行分组的实例
2017/12/08 Python
Python图形绘制操作之正弦曲线实现方法分析
2017/12/25 Python
对numpy中布尔型数组的处理方法详解
2018/04/17 Python
Django实现登录随机验证码的示例代码
2018/06/20 Python
python实现支付宝转账接口
2019/05/07 Python
python tkinter基本属性详解
2019/09/16 Python
Python二次规划和线性规划使用实例
2019/12/09 Python
Python列表解析操作实例总结
2020/02/26 Python
Pytorch 使用不同版本的cuda的方法步骤
2020/04/02 Python
Win10下配置tensorflow-gpu的详细教程(无VS2015/2017)
2020/07/14 Python
使用pandas读取表格数据并进行单行数据拼接的详细教程
2021/03/03 Python
意大利男装网店:Vrients
2019/05/02 全球购物
有影响力的品牌之家:Our Social Collective
2019/06/08 全球购物
家长学校实施方案
2014/03/15 职场文书
小学生倡议书范文
2014/05/13 职场文书
朋友离别感言
2015/08/04 职场文书
关于远足的感想
2015/08/10 职场文书
感恩的心主题班会
2015/08/12 职场文书
2016年第十九届推普周活动总结
2016/04/06 职场文书