Reflect / validate private variables in Python

If I have:

def f(x): def g(y): return x + y return g f2 = f(2) 

Is there a way to find the x binding that f2 will use? I looked at inspect , but couldn't tell if any frame material would work. In other words, can I define closed_vars() below:

 def closed_vars(anF): ... return ... assert closedVars(f2) == {'x': 2} 
+9
closures python
source share
3 answers

You do not need to use the inspect module here.

 >>> dict(zip(f2.func_code.co_freevars, (c.cell_contents for c in f2.func_closure))) {'x': 2} 

works in Python 2.7

+7
source share

You can get the contents of a cell by checking f.func_closure (works in Python 2.7.5):

 >>> def f(x): ... def g(y): ... return x + y ... return g ... >>> f2 = f(2) >>> [cell.cell_contents for cell in f2.func_closure] [2] 

Python 3.3 has the inspect.getclosurevars function:

Get the mapping of external references to names in a Python function or method to their current values. The named tuple ClosureVars(nonlocals, globals, builtins, unbound) returned. Nonlocal names transform reference names into lexical closure variables, global variables into global variables of a function module and built-in functions that are visible from the function body. unbound is a set of names referenced by a function that cannot be resolved at all, given the current global variables and built-in modules.

I'm not sure yet if you can get private variable names before Python 3.3.

+5
source share

Python 3 update - February 2019

Intentionally writing this out of the blue:

 def f(x): def g(y): return x + y return g f2 = f(2) def closedVars(anF): keys = f2.__code__.co_freevars values = [cell.cell_contents for cell in f2.__closure__] # keys and values definitely match in correct order in general case? return dict(zip(keys, values)) assert closedVars(f2) == {'x': 2} 

What is less clear to me, and this applies to the answer marked as correct, as well as to the question of whether the order between the tuple (nonlocal closure) of variable names ( __code__.co_freevars ) and the order of variable values ​​( f2.__closure__ ) are guaranteed to match (what the zip operation depends on). In the simple example used to pose the question, we are dealing with only one variable x , so the above will be enough for this particular case.

Would it be nice if someone could confirm the general case, and not just assume that this is so?

0
source share

All Articles