当前位置: 首页 > 工具软件 > Bottle > 使用案例 >

Bottle源码解读——用描述符做缓存

崔绍辉
2023-12-01

在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实现了缓存、去除()、设置只读属性三种功能,除此之外还有最通用的功能——抽象并统一管理属性。

 类似资料: