Python 描述符(Descriptor) 附实例
在 Python 众多原生特性中,描述符可能是最少被自定义的特性之一,但它在底层实现的方法和属性却无时不刻被使用着,它优雅的实现方式体现出 Python 简洁之美。
定义
- 一个描述符是一个有"绑定行为"的对象属性(object attribute),它的访问控制会被描述器协议方法重写。
- 任何定义了
__get__,__set__或者__delete__任一方法的类称为描述符类,其实例对象便是一个描述符,这些方法称为描述符协议。 - 当对一个实例属性进行访问时,Python 会按
obj.__dict__→type(obj).__dict__→type(obj)的父类.__dict__顺序进行查找,如果查找到目标属性并发现是一个描述符,Python 会调用描述符协议来改变默认的控制行为。 - 描述符是
@property@classmethod@staticmethod和super的底层实现机制。
特性
- 同时定义了
__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 value
class 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
参考文章
https://pyzh.readthedocs.io/en/latest/Descriptor-HOW-TO-Guide.html
欢迎关注

编程思维不应只存留在代码之中,更应伴随于整个人生旅途,这个公众号不只聊技术,还会聊产品/互联网/经济学等广泛话题,所以也欢迎非程序员关注。
Python 描述符(Descriptor) 附实例的更多相关文章
- python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解
1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...
- Python 描述符(descriptor) 杂记
转自:https://blog.tonyseek.com/post/notes-about-python-descriptor/ Python 引入的“描述符”(descriptor)语法特性真的很黄 ...
- python描述符descriptor(一)
Python 描述符是一种创建托管属性的方法.每当一个属性被查询时,一个动作就会发生.这个动作默认是get,set或者delete.不过,有时候某个应用可能会有 更多的需求,需要你设计一些更复杂的动作 ...
- python描述符 descriptor
descriptor 在python中,如果一个新式类定义了__get__, __set__, __delete__方法中的一个或者多个,那么称之为descriptor.descriptor通常用来改 ...
- Python 描述符 (descriptor)
1.什么是描述符? 描述符是Python新式类的关键点之一,它为对象属性提供强大的API,你可以认为描述符是表示对象属性的一个代理.当需要属性时,可根据你遇到的情况,通过描述符进行访问他(摘自Pyth ...
- Python描述符 (descriptor) 详解
1.什么是描述符? python描述符是一个“绑定行为”的对象属性,在描述符协议中,它可以通过方法重写属性的访问.这些方法有 __get__(), __set__(), 和__delete__().如 ...
- python描述符descriptor(二)
python内置的描述符 python有些内置的描述符对象,property.staticmethod.classmethod,python实现如下: class Property(object): ...
- 【python】描述符descriptor
开始看官方文档,各种看不懂,只看到一句Properties, bound and unbound methods, static methods, and class methods are all ...
- python理解描述符(descriptor)
Descriptor基础 python中的描述符可以用来定义触发自动执行的代码,它像是一个对象属性操作(访问.赋值.删除)的代理类一样.前面介绍过的property是描述符的一种. 大致流程是这样的: ...
随机推荐
- C. Divide by Three DP
http://codeforces.com/contest/792/problem/C 这题奇葩题我居然用dp过了. 如果要模拟的话,可以用一个栈保存,保存每一个%3 = 2的pos,%3 = 1的p ...
- 安卓新的联网方式 Volley的使用(一)加载图片与 json
最近刚接触安卓, 以前搞wp ,一对比起来 ,安卓怎么这么麻烦.联网必须要重新开一个线程才可以.而且加载网络图片也很麻烦...花了很久一直卡在快速滑动加载网络图片的listview上面 ,一直很纠结痛 ...
- qq登录,新浪微博登录接口申请过程中遇到的问题
接口申请下来了,开发很容易的,参数传到就可以了.以前就做过这方面的开发,但是申请还是第一次,网上有关这方面的东东不是很多,所以记录一下申请过程. 1,qq登录接口申请 申请地址是:http://con ...
- 【持续更新】HTML5 基础知识
文档类型声明 <!DOCTYPE html> 必不可少,位于文件第一行. 字符编码 <meta charset="UTF-8"> 语义化标记元素 heade ...
- 国内的Jquery CDN免费服务
Jquery是个非常流行的JS前端框架,在很多网站都能看到它的身影.很多网站都喜欢采用一些Jquery CDN加速服务,这样网站加载jquery会更快.之前火端网络的一些网站都是使用Google的jq ...
- DataGridView使用技巧(七、设定列宽和行高自动调整)----.NET
DataGridView使用技巧(七.设定列宽和行高自动调整)----.NET 1) 设定行高和列宽自动调整 [VB.NET]' 设定包括Header和所有单元格的列宽自动调整DataGridView ...
- tomcat+nginx 横向扩展
1.分别在电脑上部署两个tomcat tomcat1 tomcat2 2.不是nginx 并启动 输入 localhost 并进入nginx欢迎界面,证明部署成功 3.修改nginx 配置 ngin ...
- HDOJ 4509 湫湫系列故事——减肥记II(2013腾讯编程马拉松) 并查集合并区间
发现这种合并区间的题目还可以这么玩 给你n段时间 然后问没被占用的时间是多少 题目所给的区间是右开的导致我wa 好多人5e5*1440的暴力跑出来的时间居然只是我的两倍 不懂.... 所以并查集并没有 ...
- (三)VMware harbor使用http访问
参考:https://www.cnblogs.com/biglittleant/p/7283738.html harbor使用http访问 如果使用http启动harbor需要在docker中配置-- ...
- "Uncaught SyntaxError: Unexpected token <"错误完美解决
今天写代码的时候发现了"Uncaught SyntaxError: Unexpected token <" <html>的js错误,而且还是html的第一行,我就 ...