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?
- You should remember that
@decorator
is just a syntactic sugar forfunc = 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(...)
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 receivesfunc
as second argument.You should write
self.cache
in awrapper
closure, sowrapper
would reference correspondingdecorator
object. Writing justcache
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
Extending Setuptools Extension to Use Cmake in Setup.Py
How to Take a Screenshot/Image of a Website Using Python
How to Make Sure If Some HTML Elements Are Loaded for Selenium + Python
Change the Color of Text Within a Pandas Dataframe HTML Table Python Using Styles and CSS
How to Find Tag with Particular Text with Beautiful Soup
Detect New or Modified Files with Python
How I Open Remote Server Folder Using Python
Assign Environment Variables from Bash Script to Current Session from Python
Boto3 Client Noregionerror: You Must Specify a Region Error Only Sometimes
How to Execute Python File in Linux
Python/Ipython Importerror: No Module Named Site
Authenticate from Linux to Windows SQL Server with Pyodbc
Apt-Get Install for Different Python Versions
Postgresql: How to Install Plpythonu Extension
What Does a Python Process Return Code -9 Mean