3 ms·
>>> def makeAdder(x): def inc(y): return y+x return inc >>> f = makeAdder(3) >>> f(4) 7 So far, so good. >>> def makeAdder2(x):
by silentbicycle 18y ago
>>> def makeAdder(x):
def inc(y):
return y+x
return inc
>>> f = makeAdder(3)
>>> f(4)
7
So far, so good.
>>> def makeAdder2(x):
v = x
def inc(y):
v += y
return v
return inc
>>> f2 = makeAdder2(3)
>>> f2(4)
Traceback (most recent call last):
File "<pyshell#15>", line 1, in <module>
f2(4)
File "<pyshell#13>", line 4, in inc
v += y
UnboundLocalError: local variable 'v' referenced before assignment
>>>
It looks like you can't mutate variables in a closure. Am I doing it wrong? If you really can't, that seriously limits their power.
--
In Lua:
> function adder(x)
local v = x
function inc(y)
v = v + y
return v
end
return inc
end
>> >> >> >> >> >> >> > f = adder(3)
> =f(4)
7
> =f(4)
11
> =f(4)
15
>
Works fine. (Also, the syntax is really clean.)
- eru 18y agoYou may need to add a 'global' statement or something similiar. If you are going to mutate a variable in a function Python assumes that you want to create a new variable in that scope. Generally I do not mutate variables as far as possible, so I have not hit this problem myself, yet. Perhaps there is someone more knowledgeable about Python to step in.
- silentbicycle 18y agoBut it's not a global variable, it's scoped within the closure. So, this means Python doesn't have lexical scoping?
- eru 18y agoIt has. Just the syntax was a bit awkward when modifying variables of higher scope. See sibling comment.
- EliAndrewC 18y agoPython 3.0 fixes this with the nonlocal statement. However, you are correct that this doesn't work in Python 2.5 and earlier.
- silentbicycle 18y agoOk, thanks.
- anamax 18y agoArgh - I can't get the formatting to work. def makeAdder2(x): v = [x,] def inc(y): v[0] += y return v[0] return inc works just fine in all pythons with closures (2.0 and above?) def makeAdder2(x): def inc(y, v=[x,]): v[0] += y return v[0] return inc Also works and provides a mechanism for resetting the state.
- silentbicycle 18y agoInteresting. So keeping a reference to a list with the value works, but the value directly doesn't? Thanks for the note. Good to know it's possible, though I'd rather it handle closures / lexical scoping directly.