Yes, a decorator can be used in this instance (and it might actually be benefitial), however, it's not as simple as defining a function. In this case, what you would want to do is define what is known as a functor. A functor is a class that works as a function would.
In example, say you had the class Apple
. You might instantiate an object of this class by doing the following:
apple = Apple(color='red')
And now, if this were a functor, you could take this a step further by using the apple
object as if it were a function by calling it with apple()
. This can be used to create the decorator you are trying to make. You will initialize the check_karma
class in the decorator's definition like so:
@check_karma(needed_karma)
def hello_world():
...
This is because a decorator must be a function that returns another function. What the snippet above is essentially doing is this:
def hello_world():
...
hello_world = check_karma(needed_karma)(hello_world)
and then every time we call hello_world, we are calling the function that was returned by the check_karma
functor. user_karma
should probably requested from elsewhere.
Here is an example of how you might apply this in code:
user_karma = 50 # pretend this is where you store `user_karma`.
class KarmaRestrictor:
def __init__(self, needed_karma):
self.needed_karma = needed_karma
def __call__(self, restricted_func):
# This is the actual decoration routine. This `__call__` descriptor
# is what makes this class a **functor**.
def _restricted_func(*args, **kwargs):
if self.get_user_karma() >= self.needed_karma:
return restricted_func(*args, **kwargs)
else:
# TODO: Maybe have a failure routine?
pass
return _restricted_func
def get_user_karma(self):
return user_karma # wherever you store this.
check_karma = KarmaRestrictor # give this decorator an alias.
@check_karma(20)
def hello_world():
print 'Hello World'