Local functions in Python

Local functions in Python

I believe youre correct in seeing this as a mutability problem. While the code you posted does throw an UnboundLocalError, the following code does not:

def outer():
    a = 0
    def inner():
        print a
    inner()
outer()

Python doesnt allow you to reassign the value of a variable from an outer scope in an inner scope (unless youre using the keyword global, which doesnt apply in this case).

Check out the bottom section of the classes documentation in this Python 2.6.2 documentation:

9.2. Python Scopes and Namespaces

[…] If a name is declared global, then all references and assignments go
directly to the middle scope containing the module’s global names.
Otherwise, all variables found outside of the innermost scope are
read-only (an attempt to write to such a variable will simply create a
new local variable in the innermost scope, leaving the identically
named outer variable unchanged).

Your UnboundLocalError is because your function is actually declaring a new variable called a and then immediately trying to do a += operation on it, but this fails because a does not have a value yet. (View the a+=1 as a = a+1 and you can see the problem if a is undefined).

In general, if youre going to want to modify a, the way people usually get around it is to use a mutable type to pass a around (such as a list or a dictionary). You can modify a via the contents of the mutable type (as you probably noticed in your testing with this setup).

Hope that helps!

You should specify your variable as nonlocal to preserve its state in closure, so definition should be like this

def outer():
    a = 0
    def inner():
        nonlocal a
        a += 1
    inner()

Local functions in Python

Try binding the variable as an argument.

def outer():
    a = 0
    def inner(a=a):
        a += 1

    inner()

outer()

Ill try and dig up the appropriate documents.

edit

Since you want the inner function to have a side effect on the outer scope, then you need to use a mutable datatype like a list. Integers and strings are immutable.

def outer():
    a = [0]
    def inner():
        a[0] += 1
    inner()
    print a[0]
outer()

Leave a Reply

Your email address will not be published. Required fields are marked *