closures and dynamic binding
Terry Reedy
tjreedy at udel.edu
Sun Sep 28 17:47:44 EDT 2008
Aaron "Castironpi" Brady wrote:
> On Sep 28, 2:52 am, Steven D'Aprano <st... at REMOVE-THIS-
>> As for why the complicated version works, it may be clearer if you expand
>> it from a one-liner:
>>
>> # expand: f[ n ]= (lambda n: ( lambda: n ) )( n )
>>
>> inner = lambda: n
>> outer = lambda n: inner
>> f[n] = outer(n)
>>
>> outer(0) => inner with a local scope of n=0
>> outer(1) => inner with a local scope of n=1 etc.
For this to work, the 'expansion' has to be mental and not actual.
Which is to say, inner must be a text macro to be substituted back into
outer.
>> Then, later, when you call inner() it grabs the local scope and returns
>> the number you expected.
>
> I must have misunderstood. Here's my run of your code:
I cannot speak to what Steven meant, but
>>>> inner = lambda: n
when inner is actually compiled outside of outer, it is no longer a
closure over outer's 'n' and 'n' will be looked for in globals instead.
>>>> outer = lambda n: inner
>>>> outer(0)
> <function <lambda> at 0x00A01170>
>>>> a=outer(0)
>>>> b=outer(1)
>>>> a()
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<stdin>", line 1, in <lambda>
> NameError: global name 'n' is not defined
>
> Why doesn't 'inner' know it's been used in two different scopes, and
> look up 'n' based on the one it's in?
That would be dynamic rather than lexical scoping.
More information about the Python-list
mailing list