Static caching property

Steven D'Aprano steve at pearwood.info
Mon Mar 21 20:05:43 EDT 2016


On Tue, 22 Mar 2016 04:48 am, Ian Kelly wrote:

> You don't actually need a metaclass for this:
> 
>>>> class Desc:
> ...     def __get__(self, obj, type=None):
> ...         if not type._cached_value:
> ...             type._cached_value = compute_value(type)
> ...         return type._cached_value


This won't quite work. What if the cached value happens to be falsey, yet
still expensive to compute? You should compare it to a known sentinel which
the expensive function will never return (possibly None). Or use a hasattr
test: if not hasattr(type, '_cached_value').

But my favourite is to combine them:


class Desc:
    def __get__(self, obj, type):
        sentinel = object()  # guaranteed to be unique
        value = getattr(type, _cached_value, sentinel)
        if value is sentinel:
            value = type._cached_value = compute_value(type)
        return value



Also, you don't need the default type=None. The descriptor protocol should
never call __get__ without supplying the type. The obj may be None, but I
don't believe there are any circumstances where type will be None.

Which is good, because if it is:

AttributeError: 'NoneType' object has no attribute '_cached_value'



-- 
Steven




More information about the Python-list mailing list