I have a use case where I want to decorate a method with an additional way to call it, such as in this code:
def decorator(func):
def enhanced(*args, **kwargs):
func(*args, **kwargs)
func.enhanced = enhanced
return func
@decorator
def function():
pass
class X:
@decorator
def function(self):
pass
x = X()
function()
function.enhanced()
x.function()
# x.function.enhanced()
x.function.enhanced(x)
The first three calls work as expected, but x.function.enhanced()
does not; I'd have to write x.function.enhanced(x)
to make it work. I know that this is because the func
passed to the decorator is not a bound method but a function, and thus needs to be passed self
explicitly.
But how can I get around this? From the little bit I understand about descriptors, they're only relevant when looking up on a class, and as func
is not a class, func.enhanced
is not looked up in a way that I can intercept.
Is there something I can do here?
You can return a descriptor that returns an object that makes itself callable and has an
enhanced
attribute mapped to yourenhanced
wrapper function:so that:
would output: