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 to
returnlambda *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 before
and# do stuff after
actually run.
Post a Comment for "Class Decorator For Methods From Other Class"