# -*- 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)
Comments