memoized_property

Python
2011-06-04 01:34 (13 years ago) ytyng
# -*- coding: utf-8 -*-

"""
Use instead of property decorator.
The function is executed only once, and the calculation result is stored as an instance variable.
If it is called again, the function is not called, and the result is returned from the instance variable.

It may not work well if slots are defined.

class Hoge(object):

    @memoized_property
    def calc(self):
        some code....

For now, setters can also be set, but it's untested.
When the setter or deleter is called, it deletes the cached class variable,
so if the getter is called afterward, it should recalculate.
"""

class memoized_property(object):

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        if doc is None and fget is not None and hasattr(fget, "__doc__"):
            doc = fget.__doc__
        self.__get = fget
        self.__set = fset
        self.__del = fdel
        self.__doc__ = doc
        if fget is not None:
            self._attr_name = '___'+fget.func_name

    def __get__(self, inst, type=None):
        if inst is None:
            return self
        if self.__get is None:
            raise AttributeError("unreadable attribute")

        if not hasattr(inst, self._attr_name):
            result = self.__get(inst)
            setattr(inst, self._attr_name, result)
        return getattr(inst, self._attr_name)

    def __set__(self, inst, value):
        if self.__set is None:
            raise AttributeError("can't set attribute")
        delattr(inst, self._attr_name)
        return self.__set(inst, value)

    def __delete__(self, inst):
        if self.__del is None:
            raise AttributeError("can't delete attribute")
        delattr(inst, self._attr_name)
        return self.__del(inst)


def memoized_property_set(inst, func_name, value):
    """
    Sets a value to the attribute for memoized_property.
    The next time the property decorated with memoized_property is accessed,
    the value saved here will be used.
    """
    if isinstance(func_name, basestring):
        property_name = '___' + func_name
    elif hasattr(func_name, 'func_name'):
        property_name = '___' + func_name.func_name
    else:
        raise
    setattr(inst, property_name, value)
Currently unrated

Comments

Archive

2024
2023
2022
2021
2020
2019
2018
2017
2016
2015
2014
2013
2012
2011