在bottle中有三个描述符,cached_property和DictProperty用得最多。
深入理解Python描述符
非覆盖型的获取属性的优先级链是,getattribute->找__dict__->找描述符,这条链的规则给了"缓存属性"理论支持。
取bottle中使用的一个描述符例子
from functools import update_wrapper
class cached_property(object):
""" A property that is only computed once per instance and then replaces
itself with an ordinary attribute. Deleting the attribute resets the
property. """
def __init__(self, func):
update_wrapper(self, func) #将描述符实例self的签名改成co函数(func)
self.func = func
#当作为装饰器用时, 新生成一个描述符实例,该描述符实例保存了装饰的函数,之后可以调用
def __get__(self, instance, cls):
if instance is None: return self #如果是通过类对象调用就停止执行,返回self
value = instance.__dict__[self.func.__name__] = self.func(instance)
#将co函数计算结果存入a.__dict__,之后再调用就不会重新计算了
return value
class A:
@cached_property #co成为一个描述符实例,当通过实例a调用(a.co)的时候,执行get方法
def co(self):
return "1"
if __name__ == "__main__":
a = A()
exec(a.co) #注意这里不需要(),加了括号会报错,因为实际调用get方法而不是直接调用函数。
lazy_attribute描述符:不同于cached_property缓存结果到实例,lazy_attribute缓存结果到类对象。
对DictProperty描述符的使用介绍:
Bottle框架中的装饰器类和描述符应用
request对象中的方法经常用到DictProperty描述符
简单来说,DictProperty实现了缓存、去除()、设置只读属性三种功能,除此之外还有最通用的功能——抽象并统一管理属性。