You don’t need to mess around with descriptors. It’s enough to create a wrapper function inside the __call__()
method and return it. Standard Python functions can always act as either a method or a function, depending on context:
class MyDecorator(object):
def __init__(self, argument):
self.arg = argument
def __call__(self, fn):
@functools.wraps(fn)
def decorated(*args, **kwargs):
print "In my decorator before call, with arg %s" % self.arg
result = fn(*args, **kwargs)
print "In my decorator after call, with arg %s" % self.arg
return result
return decorated
A bit of explanation about what’s going on when this decorator is used like this:
@MyDecorator("some other func!")
def some_other_function():
print "in some other function!"
The first line creates an instance of MyDecorator
and passes "some other func!"
as an argument to __init__()
. Let’s call this instance my_decorator
. Next, the undecorated function object — let’s call it bare_func
— is created and passed to the decorator instance, so my_decorator(bare_func)
is executed. This will invoke MyDecorator.__call__()
, which will create and return a wrapper function. Finally this wrapper function is assigned to the name some_other_function
.