Class Decorator For Methods From Other Class
Solution 1:
Functions are descriptors and that's what allows them to auto-bind self. The easiest way to deal with this is to implement decorators using functions so that this is handled for you. Otherwise you need to explicitly invoke the descriptor. Here's one way:
import functools
classMyDecoratorClass:
def__init__(self, method):
functools.update_wrapper(self, method)
self.method = method
def__get__(self, instance, owner):
returntype(self)(self.method.__get__(instance, owner))
def__call__(self, *args, **kwargs):
# do stuff before
retval = self.method(*args, **kwargs)
# do stuff afterreturn retval
classFoobar:
def__init__(self):
# initialize stuffpass @MyDecoratorClassdeffoo(self, x, y):
print(f"{[self, x, y]=}")
@MyDecoratorClassdefbar(spam):
print(f"{[spam]=}")
Foobar().foo(1, 2)
bar(3)
Here the __get__ method creates a new instance of MyDecoratorClass with the bound method (previously self.method was just a function since no instance existed yet). Also note that __call__ just calls self.method(*args, **kwargs) - if self.method is now a bound method, the self of FooBar is already implied.
Solution 2:
You can implement the descriptor protocol, an example of how functions do it (but in pure python) is available in the Descriptor HOWTO, translated to your case:
import functools
import types
classMyDecoratorClass:
def__init__(self, func):
functools.update_wrapper(self, func)
self.func = func
def__call__(self, *args, **kwargs):
# do stuff before
retval = self.func(*args, **kwargs)
# do stuff afterreturn retval
def__get__(self, obj, objtype=None):
if obj isNone:
return self
return types.MethodType(self, obj)
Note, return types.MethodType(self, obj) is essentially equivalent to
returnlambda *args, **kwargs : self.func(obj, *args, **kwargs)
Note from Kristof Could it be that you meant this:
return types.MethodType(self, obj)is essentially equivalent toreturnlambda *args, **kwargs : self(obj, *args, **kwargs)Note that I replaced
self.func(..)withself(..). I tried, and only this way I can ensure that the statements at# do stuff beforeand# do stuff afteractually run.
Post a Comment for "Class Decorator For Methods From Other Class"