轻松理解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中使用PyHook监听鼠标和键盘事件实例
Jul 18 Python
python进阶教程之函数对象(函数也是对象)
Aug 30 Python
python if not in 多条件判断代码
Sep 21 Python
Python操作csv文件实例详解
Jul 31 Python
Django Admin 实现外键过滤的方法
Sep 29 Python
如何实现删除numpy.array中的行或列
May 08 Python
python实现批量解析邮件并下载附件
Jun 19 Python
python实现列表中由数值查到索引的方法
Jun 27 Python
python3对接mysql数据库实例详解
Apr 30 Python
解决pycharm 工具栏Tool中找不到Run manager.py Task的问题
Jul 01 Python
python将excel转换为csv的代码方法总结
Jul 03 Python
工程师必须了解的LRU缓存淘汰算法以及python实现过程
Oct 15 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+MySQL 制作简单的留言本
2009/11/02 PHP
md5 16位二进制与32位字符串相互转换示例
2013/12/30 PHP
PHP基于MySQLI函数封装的数据库连接工具类【定义与用法】
2017/08/11 PHP
javascript 设置某DIV区域内的checkbox复选框
2009/11/30 Javascript
jquery 弹出层注册页面等(asp.net后台)
2010/06/17 Javascript
我的javascript 函数链之演变
2011/04/07 Javascript
jQuery实现返回顶部效果的方法
2015/05/29 Javascript
jquery 实现输入邮箱时自动补全下拉提示功能
2015/10/04 Javascript
JavaScript仿微博发布信息案例
2016/11/16 Javascript
深入理解JS继承和原型链的问题
2016/12/17 Javascript
angular实现表单验证及提交功能
2017/02/01 Javascript
JS实现Cookie读、写、删除操作工具类示例
2018/08/28 Javascript
Angular8基础应用之表单及其验证
2019/08/11 Javascript
JavaScript eval()函数定义及使用方法详解
2020/07/07 Javascript
[01:09:20]NB vs NAVI Supermajor小组赛A组 BO3 第二场 6.2
2018/06/03 DOTA
跟老齐学Python之正规地说一句话
2014/09/28 Python
Python中endswith()函数的基本使用
2015/04/07 Python
详解python开发环境搭建
2016/12/16 Python
python万年历实现代码 含运行结果
2017/05/20 Python
Python的iOS自动化打包实例代码
2018/11/22 Python
11个Python3字典内置方法大全与示例汇总
2019/05/13 Python
计算机二级python学习教程(2) python语言基本语法元素
2019/05/16 Python
Python数据分析pandas模块用法实例详解
2019/11/20 Python
Selenium使用Chrome模拟手机浏览器方法解析
2020/04/10 Python
python mongo 向数据中的数组类型新增数据操作
2020/12/05 Python
CSS3中的display:grid,网格布局介绍
2019/10/30 HTML / CSS
印度网上购物首选目的地:Flipkart
2016/08/01 全球购物
美国校园市场:OCM
2017/06/08 全球购物
美国滑雪板和装备购物网站:Skis.com
2018/12/20 全球购物
eBay荷兰购物网站:eBay.nl
2020/06/26 全球购物
假日旅行社实习自我鉴定
2013/09/24 职场文书
党员查摆剖析材料
2014/10/10 职场文书
2015年网络舆情工作总结
2015/07/24 职场文书
一波干货,会议主持词开场白范文
2019/05/06 职场文书
nginx location中多个if里面proxy_pass的方法
2021/03/31 Servers
让文件路径提取变得更简单的Python Path库
2021/05/27 Python