I want to make a decorator that creates a new function/method that makes use of an object obj
. If the decorated object is a function, obj
must be instantiated when the function is created. If the decorated object is a method, a new obj
must be instantiated and bound to each instance of the class whose method is decorated. I can't put the decoration in __init__
because the decorator modifies the function documentation. I have something like this now, but it only instantiates time
once, which is not what I want:
__all__ = ['dec', 'A']
from time import time
import inspect
def dec(f):
obj = time() # want to set on object instantiation
def new(*args, **kwargs):
f(*args, **kwargs) # Validate against definition so it doesn't go
# out of sync
print obj
# ...
try:
d = inspect.getsourcelines(f)
except IOError:
d = "<unable to fetch definition>"
else:
d = d[0][1].rstrip('\n').rstrip(':').lstrip(' ').lstrip('def')
new.__doc__ = d + "\n" + (f.__doc__ or '')
return new
class A(object):
@dec
def f(self, x):
"""something"""
print '%s.f(%s)' % (self, x)
if __name__ == '__main__':
A().f(123)
A().f(123)
A().f(123)
My idea to solve this is to check if the object passed to the decorator takes an argument self
, if so, return a method that binds obj
to self
if it's not already there, and then uses self.obj
. And then if there is no self
argument to the object passed to the decorator, just instantiate obj
inside the decorator and return a function that makes use of that.
However... what I said doesn't really work for me because in my real decorator, I return an object that is derived from list
and has a __call__
attribute. Furthermore in the real decorator, self
is not even defined in the objects that get decorated by it because they don't make use of their instance variables (what I'm really decorating are just events to be subscribed to by external objects, the events have documented signatures).
Edit: Actually, if there's a way to make a list
subclass instance get bound to an instance so that it's __call__
attribute implicitly receives the class instance (like in any normal instance method), this would be a perfect solution, this was what I was originally trying to figure out how to do. But maybe there is an even better solution such that I don't have to define the decorated methods with the self
attribute? Either is perfect.