Reputation: 43206
I am trying to make a function that will cache some of it's attributes as these take some computation to return a result. Since it is the same result, I wanted to cache this in some way that allows for reusing.
Some code to put this in perspective:
This is what my proposed decorator looks like:
def cachedAttributes(func, **kwargs):
func.__dict__.update(kwargs)
return func
The class method I am trying to decorate:
class someclass:
@staticmethod
def method(*args):
# compile regex operation
# compile regex operation
# compile regex operation
# compute and return something
...
pass
This is how I am using the decorator
class someclass:
@staticmethod
@cachedAttributes(method, doctyperegex = re.compile(r'<!DOCTYPE.*?>\s*', re.S|re.U),
htmlregex = re.compile(r'<html.*?>\s*', re.S|re.U),
metaregex = re.compile(r'<meta(.*?)>', re.S|re.U))
def method(*args):
# compile regex operation
# compile regex operation
# compile regex operation
# compute and return something
...
pass
So the above is a representation of what I am working with. I have a class which has a static method that uses some regex objects to do some computations, and I want to cache the result of the compile regex
operations. However this gives me the following error:
@staticmethod
NameError: name 'method' is not defined
I know this is due to having not defined the method before trying to decorate it, but how else can I do this? Is there a builtin that can do this for me?
Upvotes: 0
Views: 353
Reputation: 1124238
Your decorator will be passed the method
function when Python applies the decorator. You do not need give your decorator factory the method as an argument:
@cachedAttributes(doctyperegex = re.compile(r'<!DOCTYPE.*?>\s*', re.S|re.U),
htmlregex = re.compile(r'<html.*?>\s*', re.S|re.U),
metaregex = re.compile(r'<meta(.*?)>', re.S|re.U))
Your cachedAttributes()
callable then returns the actual decorator:
def cachedAttributes(**kwargs):
def decorator(func):
func.__dict__.update(kwargs)
return func
return decorator
So Python calles cachedAttributes()
, which returns a decorator. That is then called passing in the function object and the return values is used as the replacement of the decorated function. That can be the original function object, like you are doing here.
Upvotes: 1
Reputation: 229561
You need to follow this common pattern: you want a function which takes the intended parameters and returns a decorator function.
def cachedAttributes(**kwargs):
def decorator(func):
func.__dict__.update(kwargs)
return func
return decorator
Then:
class someclass:
@staticmethod
@cachedAttributes(doctyperegex = re.compile(r'<!DOCTYPE.*?>\s*', re.S|re.U),
htmlregex = re.compile(r'<html.*?>\s*', re.S|re.U),
metaregex = re.compile(r'<meta(.*?)>', re.S|re.U))
def method(*args):
# compile regex operation
# compile regex operation
# compile regex operation
# compute and return something
...
pass
Upvotes: 1