Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: decorator specific argument (unrelated to wrapped function)?

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?

like image 207
Parand Avatar asked Mar 19 '09 01:03

Parand


People also ask

What is __ wrapped __ in Python?

__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.

Can decorators take arguments Python?

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.

Why do we need wrapper function in decorators?

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.

What is wrapper and decorator in Python?

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.


1 Answers

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
like image 112
fulmicoton Avatar answered Oct 26 '22 23:10

fulmicoton