Django @cache_property 原理

class cached_property(object):
    """
    Decorator that converts a method with a single self argument into a
    property cached on the instance.

    Optional ``name`` argument allows you to make cached properties of other
    methods. (e.g.  url = cached_property(get_absolute_url, name='url') )
    """

    def __init__(self, func, name=None):
        self.func = func
        self.__doc__ = getattr(func, '__doc__')
        self.name = name or func.__name__

    def __get__(self, instance, cls=None):
        if instance is None:
            return self

        res = instance.__dict__[self.name] = self.func(instance)
        return res

装饰器类解释:

  1. cache_propery为一个装饰器类,装饰某个函数
  2. 定义了一个name参数,可以自己传或者直接读取被装饰的函数名
  3. __get__方法表名这个装饰器是个描述符装饰器并且为非数据描述符
  4. 这个get方法执行了被装饰的函数并将返回的数据保存到了实例的__dict__里面
  5. 属性的读取优先级你应该要了解:数据描述符 > __dict__读取 > 非数据描述符
class RawDb(object):

    @cached_property
    def columns(self):
        return 1


rd = RawDb()
print(rd.__dict__)
print(rd.columns)

print(rd.__dict__)
print(rd.columns)

上面的打印输出:

{}
1
{‘columns’: 1}
1

解释如下:

  1. 实例rd第一次运行rd.columns,会调用__get__方法并将返回的数据保存在实例rd的__dict__里面’
  2. 访问rd.columns的时候,为什么会直接去调用描述符的 get 方法?因为当访问的属性为描述符时,会将 rd.columns 转化为RawDb.dict[‘columns’].get(rd, RawDb) 来访问。
  3. 实例rd第二次运行rd.columns,为什么不在运行__get__方法?这是因为__dict__的读取优先于非数据描述符,上面第一次运行我们已经把返回数据保存到了__dict__中,所以直接从__dict__中读取了。
    ————————————————
    版权声明:本文为CSDN博主「zhexiao27」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/andybegin/article/details/80797256
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值