博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 描述符(Descriptor) 附实例
阅读量:5771 次
发布时间:2019-06-18

本文共 1942 字,大约阅读时间需要 6 分钟。

在 Python 众多原生特性中,描述符可能是最少被自定义的特性之一,但它在底层实现的方法和属性却无时不刻被使用着,它优雅的实现方式体现出 Python 简洁之美。

定义

  • 一个描述符是一个有“绑定行为”的对象属性(object attribute),它的访问控制会被描述器协议方法重写。
  • 任何定义了 __get__, __set__ 或者 __delete__ 任一方法的类称为描述符类,其实例对象便是一个描述符,这些方法称为描述符协议。
  • 当对一个实例属性进行访问时,Python 会按 obj.__dict__type(obj).__dict__type(obj)的父类.__dict__ 顺序进行查找,如果查找到目标属性并发现是一个描述符,Python 会调用描述符协议来改变默认的控制行为。
  • 描述符是 @property@classmethod@staticmethodsuper 的底层实现机制。

特性

  • 同时定义了 __get____set__ 的描述符称为 数据描述符(data descriptor);仅定义了 __get__ 的称为 非数据描述符(non-data descriptor) 。两者区别在于:如果 obj.__dict__中有与描述符同名的属性,若描述符是数据描述符,则优先调用描述符,若是非数据描述符,则优先使用 obj.__dict__ 中属性。
  • 描述符协议必须定义在类的层次上,否则无法被自动调用。

描述符协议

__get__(self, instance, owner)

:param self: 描述符对象本身

:param instance: 使用描述符的对象的实例

:param owner: 使用描述符的对象拥有者

__set__(self, instance, value)

:param value: 对描述符的赋值

__delete__(self, instance)

实例

class LazyProperty(object):    """    实现惰性求值(访问时才计算,并将值缓存)    利用了 obj.__dict__ 优先级高于 non-data descriptor 的特性    第一次调用 __get__ 以同名属性存于实例字典中,之后就不再调用 __get__    """    def __init__(self, fun):        self.fun = fun    def __get__(self, instance, owner):        if instance is None:            return self        value = self.fun(instance)        setattr(instance, self.fun.__name__, value)        return valueclass ReadonlyNumber(object):    """    实现只读属性(实例属性初始化后无法被修改)    利用了 data descriptor 优先级高于 obj.__dict__ 的特性    当试图对属性赋值时,总会先调用 __set__ 方法从而抛出异常    """    def __init__(self, value):        self.value = value    def __get__(self, instance, owner):        return self.value    def __set__(self, instance, value):        raise AttributeError(            "'%s' is not modifiable" % self.value         )class Circle(object):    pi = ReadonlyNumber(3.14)    def __init__(self, radius):        self.radius = radius    @LazyProperty    def area(self):        print('Computing area')        return self.pi * self.radius ** 2复制代码

参考文章

欢迎关注

微信公众号:面向人生编程

编程思维不应只存留在代码之中,更应伴随于整个人生旅途,这个公众号不只聊技术,还会聊产品/互联网/经济学等广泛话题,所以也欢迎非程序员关注。

转载地址:http://vupux.baihongyu.com/

你可能感兴趣的文章
HTML5 CANVAS画图 beginPath和closePath
查看>>
C语言 for循环之阶乘的算法
查看>>
测试1T2
查看>>
Windows Azure 网站 (WAWS) 和中间证书
查看>>
iostat 离线安装
查看>>
堆和栈的区别(转过无数次的文章)
查看>>
BZOJ 4066 kd-tree 矩形询问求和
查看>>
基于springboot1.5.9整合shiro时出现静态文件找不到的问题
查看>>
js获取url参数值
查看>>
android 笔记(Service)
查看>>
curl分别以get,post方式请求https协议接口api
查看>>
无法识别system.web/system.web.extensions属性节点
查看>>
Excel考勤统计要每个人的每天的第一卡和最后一卡
查看>>
Go 简单测试
查看>>
第二阶段冲刺第十天
查看>>
WinForm窗体的创建于传值(1)
查看>>
参数化
查看>>
Get vs Post http://blog.teamtreehouse.com/the-definitive-guide-to-get-vs-post
查看>>
洛谷P1122 最大子树和
查看>>
POJ2513 Colored Sticks
查看>>