pythonscopetracebackinspectfree-variable

How to access a FREE variable of a function from outside


Let's consider we have a function and an inner function like this (which we can not change):

from functools import wraps
def outer_f(some_callable):
    def inner_f(v):
        return some_callable(v) + 1
    return inner_f

And we only obtain a function 'func' which is the called version of outer_f which corresponds to inner_f like that:

>>> func = outer_f(int)

In such a case, the variable named 'some_callable' is the type int and if we call func with a parameter we get an answer like this:

>>> func('1')
2

I would like to access some_callable from outside of function when I only have func function instance (which means after outer_f is called).

If I am not mistaken, some_callable is a free variable of the function inner_f (func.func_code.co_freevars). How can I know that func is called with parameter int with only looking at func?

I was unable to solve the problem using inspect module or looking at attributes of the function. Methods like calling func with trace module then inspecting the stack trace or using pdb seems promising but they would be kind of ugly hacks.

This question simply reduces to access a free variable of a function's scope from outside.

So how can I know that the free variable 'some_callable' is 'int' without executing the func?


Solution

  • You can do:

    import inspect
    result = inspect.getclosurevars(func).nonlocals['some_callable']
    

    Example:

    >>> from functools import wraps
    >>>
    >>> def outer_f(some_callable):
    ...     def inner_f(v):
    ...         return some_callable(v) + 1
    ...     return inner_f
    ...
    >>>
    >>> func = outer_f(int)
    >>>
    >>> import inspect
    >>> result = inspect.getclosurevars(func).nonlocals['some_callable']
    >>>
    >>> result
    <class 'int'>