Wrap any function or method by container class using a decorator

19 Views Asked by At

In Python, I would like to wrap both decorated functions or methods into a container class holding additional information and generally mark functions as "externally callable".

Given this little program rudely explains my attempt. This works with functions, but not with methods that belong to a class, as the self argument is expected.

from typing import Callable


class Exposed:
    def __init__(self, func: Callable):
        self.func = func

    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs)


def exposed(func: Callable) -> Exposed:
    return Exposed(func)


@exposed
def add(x, y):
    return x + y


class MyClass:
    def __init__(self, value):
        self.value = value

    @exposed
    def mul(self, factor):
        return self.value * factor


result = add(3, 5)
print(result)  # 8

obj = MyClass(5)
result = obj.mul(3)
print(result)  # 15

when running this, the following error occurs:

$ python x.py
8
Traceback (most recent call last):
  File "~/x.py", line 34, in <module>
    result = obj.mul(3)
             ^^^^^^^^^^
  File "~/x.py", line 9, in __call__
    return self.func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: MyClass.mul() missing 1 required positional argument: 'factor'

I know that the problem is with the method, expecting the self-parameter or, more specific, a binding. When the decorator is executed, there is no binding. Maybe my entire approach is wrong, but I'm out of ideas, and several solutions I've tried didn't work. I'm on current stable Python 3.11. Can somebody help?

0

There are 0 best solutions below