Scoping Issues
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu May 24 21:50:15 EDT 2012
On Thu, 24 May 2012 18:23:18 -0700, SherjilOzair wrote:
> def adder():
> s = 0
> def a(x):
> s += x
> return sum
> return a
I think you mean "return s", not sum.
> This should work, right? Why does it not?
No, it shouldn't. When you have an assignment, such as "s += x", Python
treats s as a local variable. Since s is local to the inner function a(),
it has no initial value, and the += fails.
In Python 3, you can declare s to be a non-local variable with the
nonlocal keyword:
def adder():
s = 0
def a(x):
nonlocal s
s += x
return s
return a
which now works the way you should expect:
>>> add = adder()
>>> add(1)
1
>>> add(2)
3
>>> add(5)
8
But in Python 2, which you are using, there is no nonlocal keyword and
you can only write to globals (declaring them with the global keyword) or
locals (with no declaration), not nonlocals.
There are a number of work-arounds to this. One is to use a callable
class:
class Adder:
def __init__(self):
self.s = 0
def __call__(self, x):
self.s += x
return self.s
Another is to use an extra level of indirection, and a mutable argument.
Instead of rebinding the non-local, you simply modify it in place:
def adder():
s = [0]
def a(x):
s[0] += x
return s[0]
return a
--
Steven
More information about the Python-list
mailing list