Reputation: 682
I want to decorate a class method, but at runtime (by that I mean that the decorator does not need to be specified before the method with the @ notation)
See this example of a standard method decorator:
def method_decorator(func):
def decorated(self, *args, **kwargs):
print('decorator:', args, kwargs)
return func(self,*args, **kwargs)
return decorated
class Standard():
@ method_decorator
def decorated(self, *args, **kwargs):
print('decorated: ', args, kwargs)
s = Standard()
s.decorated(1,2)
Result:
decorator: (1, 2) {}
decorated: (1, 2) {}
So I tried different ways to do it at runtime:
class RunTime():
def set_decorator_1(self, decorator):
self.decorated = decorator(self.decorated)
def set_decorator_2(self, decorator):
RunTime.decorated = decorator(RunTime.decorated)
def set_decorator_3(self, decorator):
self.decorated = decorator(RunTime.decorated)
def set_decorator_4(self, decorator):
setattr(self, 'decorated', decorator(RunTime.decorated))
def set_decorator_5(self, decorator):
setattr(self, 'decorated', decorator(self.decorated))
def decorated(self, *args, **kwargs):
print('decorated: ', args, kwargs)
r = RunTime()
r.set_decorator_*(method_decorator)
r.decorated(1,2)
And here are the outputs:
decorator: (2,) {}
decorated: (1, 2) {}
decorator: (2,) {}
decorated: (2,) {}
I also tries another decorator, which works well (with set_decorator_1) but does not allow me to access self in it:
def method_decorator_runtime(func):
def decorated( *args, **kwargs):
print('decorator: ', args, kwargs)
return func( *args, **kwargs)
return decorated
Does anyone know a proper way of decorating a method at run time, with ability to access self in the decorator ?
Upvotes: 0
Views: 482
Reputation: 1610
The closest solution I have found for your question is to use a decorator with an argument where you can pass the instance of the object that has its method decorated.
def method_decorator(self_eventually):
def decorator(func):
def decorated(*args, **kwargs):
print('decorator:', repr(self_eventually), args, kwargs)
return func(*args, **kwargs)
return decorated
return decorator
class RunTime():
def set_decorator(self, decorator):
self.decorated = decorator(self)(self.decorated)
def decorated(self, *args, **kwargs):
print('decorated:', repr(self), args, kwargs)
r = RunTime()
r.set_decorator(method_decorator)
r.decorated(1, 2)
Upvotes: 1