在 Python 众多原生特性中,描述符可能是最少被自定义实现的特性之一,很多初学者都可能不知道它的存在,但它在底层实现的方法和属性却随处可见,它优雅的实现方式充分体现出 Python 的简洁之美。
__get__
, __set__
或者 __delete__
任一方法的类称为描述符类,其实例对象便是一个描述符,这些方法称为描述符协议。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
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有