Python中的descriptor描述器简明使用指南


Posted in Python onJune 02, 2016

当定义迭代器的时候,描述是实现迭代协议的对象,即实现__iter__方法的对象。同理,所谓描述器,即实现了描述符协议,即__get__, __set__, 和 __delete__方法的对象。

单看定义,还是比较抽象的。talk is cheap。看代码吧:

class WebFramework(object):
  def __init__(self, name='Flask'):
    self.name = name

  def __get__(self, instance, owner):
    return self.name

  def __set__(self, instance, value):
    self.name = value


class PythonSite(object):

  webframework = WebFramework()

In [1]: PythonSite.webframework
Out[1]: 'Flask'

In [2]: PythonSite.webframework = 'Tornado'

In [3]: PythonSite.webframework
Out[3]: 'Tornado'

定义了一个类WebFramework,它实现了描述符协议__get__和__set__,该对象(类也是对象,一切都是对象)即成为了一个描述器。同时实现__get__和__set__的称之为资料描述器(data descriptor)。仅仅实现__get__的则为非描述器。两者的差别是相对于实例的字典的优先级。

如果实例字典中有与描述器同名的属性,如果描述器是资料描述器,优先使用资料描述器,如果是非资料描述器,优先使用字典中的属性。

描述器的调用
对于这类魔法,其调用方法往往不是直接使用的。例如装饰器需要用 @ 符号调用。迭代器通常在迭代过程,或者使用 next 方法调用。描述器则比较简单,对象属性的时候会调用。

In [15]: webframework = WebFramework()

In [16]: webframework.__get__(webframework, WebFramework)
Out[16]: 'Flask'

描述器的应用
描述器的作用主要在方法和属性的定义上。既然我们可以重新描述类的属性,那么这个魔法就可以改变类的一些行为。最简单的应用则是可以配合装饰器,写一个类属性的缓存。Flask的作者写了一个werkzeug网络工具库,里面就使用描述器的特性,实现了一个缓存器。

class _Missing(object):
  def __repr__(self):
    return 'no value'

  def __reduce__(self):
    return '_missing'


_missing = _Missing()


class cached_property(object):
  def __init__(self, func, name=None, doc=None):
    self.__name__ = name or func.__name__
    self.__module__ = func.__module__
    self.__doc__ = doc or func.__doc__
    self.func = func

  def __get__(self, obj, type=None):
    if obj is None:
      return self
    value = obj.__dict__.get(self.__name__, _missing)
    if value is _missing:
      value = self.func(obj)
      obj.__dict__[self.__name__] = value
    return value


class Foo(object):
  @cached_property
  def foo(self):
    print 'first calculate'
    result = 'this is result'
    return result


f = Foo()

print f.foo  # first calculate this is result
print f.foo  # this is result

运行结果可见,first calculate只在第一次调用时候被计算之后就把结果缓存起来了。这样的好处是在网络编程中,对HTTP协议的解析,通常会把HTTP的header解析成python的一个字典,而在视图函数的时候,可能不知一次的访问这个header,因此把这个header使用描述器缓存起来,可以减少多余的解析。

描述器在python的应用十分广泛,通常是配合装饰器一起使用。强大的魔法来自强大的责任。描述器还可以用来实现ORM中对sql语句的"预编译"。恰当的使用描述器,可以让自己的Python代码更优雅。

Python 相关文章推荐
详解Python中find()方法的使用
May 18 Python
Python如何抓取天猫商品详细信息及交易记录
Feb 23 Python
Django实战之用户认证(用户登录与注销)
Jul 16 Python
flask入门之文件上传与邮件发送示例
Jul 18 Python
对python 操作solr索引数据的实例详解
Dec 07 Python
Python多图片合并PDF的方法
Jan 03 Python
自定义django admin model表单提交的例子
Aug 23 Python
python中图像通道分离与合并实例
Jan 17 Python
从训练好的tensorflow模型中打印训练变量实例
Jan 20 Python
面向新手解析python Beautiful Soup基本用法
Jul 11 Python
简单的命令查看安装的python版本号
Aug 28 Python
浅谈Python数学建模之整数规划
Jun 23 Python
Python黑魔法Descriptor描述符的实例解析
Jun 02 #Python
深入理解Python变量与常量
Jun 02 #Python
Python中的Descriptor描述符学习教程
Jun 02 #Python
从源码解析Python的Flask框架中request对象的用法
Jun 02 #Python
Python搭建APNS苹果推送通知推送服务的相关模块使用指南
Jun 02 #Python
Python的Django框架中使用SQLAlchemy操作数据库的教程
Jun 02 #Python
实例解析Python中的__new__特殊方法
Jun 02 #Python
You might like
PHP正则替换函数preg_replace和preg_replace_callback使用总结
2014/09/22 PHP
php格式化电话号码的方法
2015/04/24 PHP
PHP合并数组函数array_merge用法分析
2017/02/17 PHP
Mozilla 表达式 __noSuchMethod__
2009/04/05 Javascript
Jquery 最近浏览过的商品的功能实现代码
2010/05/14 Javascript
为jQuery增加join方法的实现代码
2010/11/28 Javascript
javascript获取web应用根目录的方法
2014/02/12 Javascript
使用CSS+JavaScript或纯js实现半透明遮罩效果的实例分享
2016/05/09 Javascript
jQuery实现的导航下拉菜单效果
2016/07/04 Javascript
canvas时钟效果
2017/02/16 Javascript
ReactNative 之FlatList使用及踩坑封装总结
2017/11/29 Javascript
一个基于react的图片裁剪组件示例
2018/04/18 Javascript
通过实践编写优雅的JavaScript代码
2019/05/30 Javascript
解决nuxt页面中mounted、created、watch执行两遍的问题
2020/11/05 Javascript
用vue设计一个日历表
2020/12/03 Vue.js
Python中type的构造函数参数含义说明
2015/06/21 Python
numpy.random.seed()的使用实例解析
2018/02/03 Python
使用python Fabric动态修改远程机器hosts的方法
2018/10/26 Python
一篇文章搞懂Python的类与对象名称空间
2018/12/10 Python
Python实现的读取文件内容并写入其他文件操作示例
2019/04/09 Python
基于python使用tibco ems代码实例
2019/12/20 Python
python中uuid模块实例浅析
2020/12/29 Python
html5-Canvas可以在web中绘制各种图形
2012/12/26 HTML / CSS
MUGLER官方网站:蒂埃里·穆勒香水
2019/11/26 全球购物
自然健康的概念:Natural Healthy Concepts
2020/01/26 全球购物
网络、C以及其他硬件方面的面试题
2016/08/23 面试题
优秀应届毕业生自荐信
2013/11/16 职场文书
社区中秋节活动方案
2014/01/29 职场文书
工程承包协议书
2014/10/20 职场文书
民事纠纷协议书
2016/03/23 职场文书
2016年“我们的节日·重阳节”主题活动总结
2016/04/01 职场文书
拥有这5个特征人,“命”都不会太差
2019/08/16 职场文书
创业计划书之溜冰场
2019/10/25 职场文书
创业计划书之酒吧
2019/12/02 职场文书
Nginx 根据URL带的参数转发的实现
2021/04/01 Servers
css常用字体属性与背景属性介绍
2022/02/28 HTML / CSS