I have a simple decorator to track the runtime of a function call:
def timed(f): def caller(*args): start = time.time() res = f(*args) end = time.time() return res, end - start return caller This can be used as follows, and returns a tuple of the function result and the execution time.
@timed def test(n): for _ in range(n): pass return 0 print(test(900)) # prints (0, 2.69e-05) Simple enough. But now I want to apply this to recursive functions. Applying the above wrapper to a recursive function results in nested tuples with the times of each recursive call, as is expected.
@timed def rec(n): if n: return rec(n - 1) else: return 0 print(rec(3)) # Prints ((((0, 1.90e-06), 8.10e-06), 1.28e-05), 1.90e-05) What's an elegant way to write the decorator so that it handles recursion properly? Obviously, you could wrap the call if a timed function:
@timed def wrapper(): return rec(3) This will give a tuple of the result and the time, but I want all of it to be handled by the decorator so that the caller does not need to worry about defining a new function for every call. Ideas?
sys._getframe, but that is an implementation detail of CPython, so it's not really part of the abstract python language. Also it's probably going to be quite slow.