I'd like to do the following:
for every nested function f anywhere in this_py_file:
if has_free_variables(f):
print warning
Why? Primarily as insurance against the late-binding closure gotcha as described elsewhere. Namely:
>>> def outer():
... rr = []
... for i in range(3):
... def inner():
... print i
... rr.append(inner)
... return rr
...
>>> for f in outer(): f()
...
2
2
2
>>>
And whenever I get warned about a free variable, I would either add an explicit exception (in the rare case that I would want this behaviour) or fix it like so:
... def inner(i=i):
Then the behaviour becomes more like nested classes in Java (where any variable to be used in an inner class has to be final
).
(As far as I know, besides solving the late-binding issue, this will also promote better use of memory, because if a function "closes over" some variables in an outer scope, then the outer scope cannot be garbage collected for as long as the function is around. Right?)
I can't find any way to get hold of functions nested in other functions. Currently, the best way I can think of is to instrument a parser, which seems like a lot of work.
Nested functionsIt can access the outer variables and so can return the full name.
A nested function can access other local functions, variables, constants, types, classes, etc. that are in the same scope, or in any enclosing scope, without explicit parameter passing, which greatly simplifies passing data into and out of the nested function. This is typically allowed for both reading and writing.
JavaScript allows for the nesting of functions and grants the inner function full access to all the variables and functions defined inside the outer function (and all other variables and functions that the outer function has access to).
A nested function is a function that is completely contained within a parent function. Any function in a program file can include a nested function.
Consider the following function:
def outer_func():
outer_var = 1
def inner_func():
inner_var = outer_var
return inner_var
outer_var += 1
return inner_func
The __code__
object can be used to recover the code object of the inner function:
outer_code = outer_func.__code__
inner_code = outer_code.co_consts[2]
From this code object, the free variables can be recovered:
inner_code.co_freevars # ('outer_var',)
You can check whether or not an code object should be inspected with:
hasattr(inner_code, 'co_freevars') # True
After you get all the functions from your file, this might look something like:
for func in function_list:
for code in outer_func.__code__.co_consts[1:-1]:
if hasattr(code, 'co_freevars'):
assert len(code.co_freevars) == 0
Someone who knows more about the inner workings can probably provide a better explanation or a more concise solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With