Say we have a function, define in my_module.py:
def make_function(scalar: float) -> Callable[[float], float]:
def increment(x: float) -> float:
return x + scalar
return increment
And on runtime, I have access to the live inner function objects (and I know that all the relevant code is defined in my_module.py).
>> make_function(2)
<function my_module.make_function.<locals>.increment(x: float) -> float>
Q: is there an elegant way, from the live object, to obtain information about what its parent function is? In particular I am interested in dynamically generating strings of the format "my_module.make_function.increment"
. I am looking for a solution which would also work for an arbitrary number of nested levels (i.e. "my_module.outer_func_1.outer_func_2.inner_func"
).
Note that the answer to my question seems to be (almost) embedded in the __repr__
of the function object as per my code sample before. But unsure about what internals are behind it and how to access them.
What have I tried?
inspect.getmodule(func).__name__
but that only returns the module pathfunc.__code__.co_*
, but couldn't find a way to point to the parent functionfunc.__globals__
, but that seemed more complex than neededIdeally I would like to avoid decorating/modifying the defined functions and only arrive at the answer from inspecting object itself. Any help on how to proceed is much appreciated!
I think the safest bet is just to use __qualname__
:
In [6]: def foo():
...: def bar():
...: def baz():
...: return 42
...: return baz
...: return bar()
...:
In [7]: f = foo()
In [8]: f
Out[8]: <function __main__.foo.<locals>.bar.<locals>.baz()>
In [9]:
In [9]: f.__qualname__
Out[9]: 'foo.<locals>.bar.<locals>.baz'
So, something like:
In [11]: f.__qualname__.replace("<locals>.", "")
Out[11]: 'foo.bar.baz'