I'm looking to build a caching decorator that given a function caches the result of the function to a location specified in the decoration. Something like this:
@cacheable('/path/to/cache/file')
def my_function(a, b, c):
return 'something'
The argument to the decorator is completely separate from the argument to the function it's wrapping. I've looked at quite a few examples but I'm not quite getting how to do this - is it possible to have an argument for the decorator that's unrelated to and not passed to the wrapped function?
__wrapped__ in Python decorators As we can see from the code of the functools module 1, when decorating an object, there is an attribute named __wrapped__ that holds the reference to the original one. So now if we use this, we can access it directly without having to resort to the old quirks.
Implementing Decorator Arguments You may expect that decorator arguments are somehow passed into the function along with this f argument, but sadly Python always passes the decorated function as a single argument to the decorator function.
The purpose of having a wrapper function is that a function decorator receives a function object to decorate, and it must return the decorated function.
In Python, a function decorator is effectively a function wrapper. A function decorator extends the functionality of a function by wrapping around it without modifying its original intended behavior. As usual, let's start with the basics and slowly work our way to finally understanding what a function decorator is.
The idea is that your decorator is a function returning a decorator.
FIRST Write your decorator as if you knew your argument was a global variable. Let's say something like:
-
def decorator(f):
def decorated(*args,**kwargs):
cache = Cache(cachepath)
if cache.iscached(*args,**kwargs):
...
else:
res = f(*args,**kwargs)
cache.store((*args,**kwargs), res)
return res
return decorated
THEN Write a function that takes cachepath as an arg and return your decorator.
-
def cache(filepath)
def decorator(f):
def decorated(*args,**kwargs):
cache = Cache(cachepath)
if cache.iscached(*args,**kwargs):
...
else:
res = f(*args,**kwargs)
cache.store((*args,**kwargs), res)
return res
return decorated
return decorator
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With