Is There a Decorator to Simply Cache Function Return Values

Is there a decorator to simply cache function return values?

Python 3.8 functools.cached_property decorator

https://docs.python.org/dev/library/functools.html#functools.cached_property

cached_property from Werkzeug was mentioned at: https://stackoverflow.com/a/5295190/895245 but a supposedly derived version will be merged into 3.8, which is awesome.

This decorator can be seen as caching @property, or as a cleaner @functools.lru_cache for when you don't have any arguments.

The docs say:

@functools.cached_property(func)

Transform a method of a class into a property whose value is computed once and then cached as a normal attribute for the life of the instance. Similar to property(), with the addition of caching. Useful for expensive computed properties of instances that are otherwise effectively immutable.

Example:

class DataSet:
def __init__(self, sequence_of_numbers):
self._data = sequence_of_numbers

@cached_property
def stdev(self):
return statistics.stdev(self._data)

@cached_property
def variance(self):
return statistics.variance(self._data)

New in version 3.8.

Note This decorator requires that the dict attribute on each instance be a mutable mapping. This means it will not work with some types, such as metaclasses (since the dict attributes on type instances are read-only proxies for the class namespace), and those that specify slots without including dict as one of the defined slots (as such classes don’t provide a dict attribute at all).

Decorator for a class method that caches return value after first access

First of all Test should be instantiated

test = Test()

Second, there is no need for inspect cause we can get the property name from func.__name__
And third, we return property(cache) to make python to do all the magic.

def cachedproperty(func):
" Used on methods to convert them to methods that replace themselves\
with their return value once they are called. "

def cache(*args):
self = args[0] # Reference to the class who owns the method
funcname = func.__name__
ret_value = func(self)
setattr(self, funcname, ret_value) # Replace the function with its value
return ret_value # Return the result of the function

return property(cache)

class Test:
@cachedproperty
def test(self):
print "Execute"
return "Return"

>>> test = Test()
>>> test.test
Execute
'Return'
>>> test.test
'Return'
>>>

"""

How can i write python decorator for caching?

  1. You should remember that @decorator is just a syntactic sugar for func = decorator(func). So here comes a difference:

(1)

@decorator 
def func():
...

is same as

func = decorator(func)  # Just call of __init__
func(...) # Call of decorator.__call__

but (2)

@decorator(some_param)
def func():
...

is similiar to

# Call of __init__ plus call of __call__
func = decorator(some_param)(func)
# Call of closure returned by decorator.__call__
func(...)

  1. You have implemented decorator accepting arguments for (2) syntax, but do not provide them when using them as in example (1). That is why __init__ complaining, it receives func as second argument.

  2. You should write self.cache in a wrapper closure, so wrapper would reference corresponding decorator object. Writing just cache will cause global variable search and thus will fail.

UPD: I changed your code to approach (1):

class memoize:
def __init__(self, function):
self.cache = {}
self.function = function

def __call__(self, *args, **kwargs):
key = str(args) + str(kwargs)
if key in self.cache:
return self.cache[key]

value = self.function(*args, **kwargs)
self.cache[key] = value
return value

@memoize
def fib(n):
if n in (0, 1):
return 1
else:
return fib(n-1) + fib(n-2)

for i in range(0, 10):
print(fib(i))

print(fib.cache)

Is there a decorator to simply cache function return values?

Python 3.8 functools.cached_property decorator

https://docs.python.org/dev/library/functools.html#functools.cached_property

cached_property from Werkzeug was mentioned at: https://stackoverflow.com/a/5295190/895245 but a supposedly derived version will be merged into 3.8, which is awesome.

This decorator can be seen as caching @property, or as a cleaner @functools.lru_cache for when you don't have any arguments.

The docs say:

@functools.cached_property(func)

Transform a method of a class into a property whose value is computed once and then cached as a normal attribute for the life of the instance. Similar to property(), with the addition of caching. Useful for expensive computed properties of instances that are otherwise effectively immutable.

Example:

class DataSet:
def __init__(self, sequence_of_numbers):
self._data = sequence_of_numbers

@cached_property
def stdev(self):
return statistics.stdev(self._data)

@cached_property
def variance(self):
return statistics.variance(self._data)

New in version 3.8.

Note This decorator requires that the dict attribute on each instance be a mutable mapping. This means it will not work with some types, such as metaclasses (since the dict attributes on type instances are read-only proxies for the class namespace), and those that specify slots without including dict as one of the defined slots (as such classes don’t provide a dict attribute at all).



Related Topics



Leave a reply



Submit