19

I'd like to have variable defined in the nesting function to be altered in the nested function, something like

def nesting():
    count = 0
    def nested():
        count += 1

    for i in range(10):
        nested()
    print count

When nesting function is called, I wish it prints 10, but it raises UnboundLocalError. The key word global may resolve this. But as the variable count is only used in the scope of nesting function, I expect not to declare it global. What is the good way to do this?

bxx
  • 1,701
  • 2
  • 12
  • 16
  • 1
    possible duplicate of [Python overwriting variables in nested functions](http://stackoverflow.com/questions/7935966/python-overwriting-variables-in-nested-functions) – Lily Chung May 15 '14 at 21:30

3 Answers3

24

In Python 3.x, you can use the nonlocal declaration (in nested) to tell Python you mean to assign to the count variable in nesting.

In Python 2.x, you simply can't assign to count in nesting from nested. However, you can work around it by not assigning to the variable itself, but using a mutable container:

def nesting():
    count = [0]
    def nested():
        count[0] += 1

    for i in range(10):
        nested()
    print count[0]

Although for non-trivial cases, the usual Python approach is to wrap the data and functionality in a class, rather than using closures.

Thomas Wouters
  • 130,178
  • 23
  • 148
  • 122
  • What you can do is bind the variables inside the closure from the outer function, but not the other way around. consider this case (when the parent fucntion scope has gone away): def a(): test = 50 def b(y): return test+ y return b Running a will return a function that adds 50 to its parameter. This does not modify test, and test is bound. If you parameterised 'a', you could generate differennt b's - rather like higher order lisp functions. – Danny Staple Jun 01 '11 at 09:22
5

A little bit late, you can attach an attribute to "nesting" function like so:

def nesting():

    def nested():
        nested.count += 1
    nested.count = 0

    for i in range(10):
        nested()
    return nested

c = nesting()
print(c.count)
0

The most elegant approach for me: Works 100% on both python versions.

def ex8():
    ex8.var = 'foo'
    def inner():
        ex8.var = 'bar'
        print 'inside inner, ex8.var is ', ex8.var
    inner()
    print 'inside outer function, ex8.var is ', ex8.var
ex8()

inside inner, ex8.var is  bar
inside outer function, ex8.var is  bar

More: http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/

Deivydas Voroneckis
  • 1,973
  • 3
  • 19
  • 40