We have a somewhat flawed answer, but it is different than some of the other answers I have seen. Hopefully, someone can post an even better answer, because my solution to the problem has some serious issues.
import functools
import inspect
def print_calling_args(f):
assert(callable(f))
@functools.wraps(f)
def wrapper(*args, **kwargs):
siggy = inspect.signature(f)
bound_siggy = siggy.bind(*args, **kwargs)
all_sargs = ", ".join(kw + " = " + str(arg) for kw, arg in bound_siggy.arguments.items())
print(f.__qualname__, "(", all_sargs, ")", sep = "")
return f(*args, **kwargs)
return wrapper
Issue: str(arg)
is bad way to convert arguments into strings
I converted each argument arg
into a string by writing str(arg)
Suppose that you pass a pandas dataframe into a function.
We can get some very ugly output.
The resulting string can contain new-line characters \n
or carriage returns \r
.
The strings could also be a mile long.
Issue: Cannot Get the Name of a Functor
Another issue with my attempts is that Functors (also known as "function objects") do not have an attribute named __qualname__
. That is, if you define a class which has a __call__
method, then we cannot easily print the name of the functor to a string.
funky = Functor()
funky = decorate(funky)
r = funky(1, 2, 3, kwargy = int("python", 36))
# should print:
# funky(1, 2, 3 kwargy = 1570137287)
Below is an example of a functor:
# EXAMPLE OF A `FUNCTOR`
class Multiplier:
def __init__(self, m:int):
self._m = int(str(m))
def __call__(self, num:float)
return num * self._m;
multi_the_multiplier = Multiplier(10**6)
# Decorate `multi_the_multiplier` with ` print_calling_args`
multi_the_multiplier = print_calling_args(multi_the_multiplier)
# ERROR: `multi_the_multiplier` does not have a `__qualname__`
r = multi_the_multiplier(1)
r = multi_the_multiplier(2)
r = multi_the_multiplier(3)