Converting functions
Peter Otten
__peter__ at web.de
Mon Jan 24 06:55:07 EST 2011
Edmunds Cers wrote:
> Peter Otten <__peter__ at web.de> writes:
>
>> I don't know how to express it more clearly, so here's another example:
>>
>>>>> def f():
>> ... def g(): return a * a
>> ... def h(): return a + a
>> ... a = 5
>> ... return g, h
>> ...
>>>>> g, h = f()
>>>>> g(), h()
>> (25, 10)
>
> IMHO this whole confusion just shows that mingling assignment and
> binding makes understanding scope harder. In Python, the first
> assignment inside a function body also creates a binding (unless told
> not to do so by global) the scope of which is the _whole_ of the
> function body. A variable reference refers to the lexically innermost
> surrounding binding of said variable. Now, while it might seem that some
> magic happens in the example on the return of the function, this is in
> fact not so, since the assignment "a = 5" actually creates a binding for
> /a/ that is visible from the body of /g/, because the lexical scope of
> the binding is the whole body of /f/, so that the capture of the
> variable happens inside of the def expression (as one would expect) and
> not on return as you seem to imply.
>
> Slightly OT -- the above also explains why closed over variables are
> read only in Python. An assignment inside a closure would implicitly
> create a binding, so that all (even previous) references to that
> variable would refer to this new binding.
Well, in Python 3 they no longer are, courtesy of the nonlocal statement:
>>> def f():
... def set(x):
... nonlocal a
... a = x
... def get():
... return a
... return get, set
... a = 42
...
>>> get, set = f()
>>> get()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in get
NameError: free variable 'a' referenced before assignment in enclosing scope
>>> set(42)
>>> get()
42
That closed-over variables are read-only by default is just to avoid the
ambiguity about the scope they are supposed to live in, just like global
variables that are to be changed from within a function.
Peter
More information about the Python-list
mailing list