Flask源码学习--locked_cached_property

# sentinel
_missing = object()

class locked_cached_property(object):
    """A decorator that converts a function into a lazy property.  The
    function wrapped is called the first time to retrieve the result
    and then that calculated result is used the next time you access
    the value.  Works like the one in Werkzeug but has a lock for
    thread safety.
    """

    def __init__(self, func, name=None, doc=None):
        self.__name__ = name or func.__name__
        self.__module__ = func.__module__
        self.__doc__ = doc or func.__doc__
        self.func = func
        self.lock = RLock()

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        with self.lock: # 保证线程安全
            value = obj.__dict__.get(self.__name__, _missing)
            if value is _missing:
                value = self.func(obj)
                obj.__dict__[self.__name__] = value
            return value
            
class _PackageBoundObject(object):
	......
    @locked_cached_property
    def jinja_loader(self):
        """The Jinja loader for this package bound object.
        .. versionadded:: 0.5
        """
        if self.template_folder is not None:
            return FileSystemLoader(os.path.join(self.root_path,
                                                 self.template_folder))
  • locked_cached_property是一个非数据属性描述符类,在_PackageBoundObject类中,使用 locked_cached_propertyjinja_loader方法进行了装饰,使得jinjia_loader方法变成了属性描述符,这样就实现了通过obj.jinja_loader就能间接调用jinja_loader方法。
  • locked_cached_property类的__get__方法中,利用了可重入锁(RLock)保证线程安全,首次调用获取到函数返回值后,将函数的返回值缓存到了所属对象的__dict__中,这样下次调用obj.jinja_loader时,因为locked_cached_property(jinja_loader)是非数据属性描述符,所以会直接返回obj.__dict__['jinja_loader'],减少开销。

为何要要使用obj.__dict__.get(self.__name__, _missing)而不使用obj.__dict__.get(self.__name__, None)

避免被装饰函数返回值为None的情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值