This module is a nonlocal patch for Python 2.7 and PyPy. Save it as nonlocals.py. Here's a first example:

from nonlocals import * def outer(): var = 0 @nonlocals('var') def inner(): print var var = 1 print var inner() outer()

That prints:

0 1

Without nonlocals, this prints:

Traceback (most recent call last): File "ex1.py", line 11, in <module> outer() File "ex1.py", line 10, in outer inner() File "ex1.py", line 7, in inner print var UnboundLocalError: local variable 'var' referenced before assignment

However, right now, changes to var made in inner don't propagate to outer . Example:

from nonlocals import * def outer(): var = 0 @nonlocals('var') def inner(): print var var = 1 print var inner() print var outer()

That prints:

0 1 0

This is largely because of the way Python does certain things. In order to get around it, use export_nonlocals :

from nonlocals import * @export_nonlocals('var') def outer(): var = 0 @nonlocals('var') def inner(): print var var = 1 print var inner() print var outer()

export_nonlocals sets up variables so they can be modified from inner . Now, it prints:

0 1 1

How it works:

export_nonlocals changes all local variable references in a way so that they modified by other scopes by replacing LOAD_FAST and STORE_FAST codes that modify the given variables to LOAD_NAME and STORE_NAME, moving the variable reference to external names, and using bitwise NOT to change the compile flags. nonlocals works by changing LOAD_FAST and STORE_FAST codes that modify the given variables with LOAD_DEREF and STORE_DEREF and modifying outer 's locals if export_nonlocals was used.

This is very hackish and plays with CPython internal implementation stuff that PyPy just happens to be compatible with. YOU WERE WARNED!!!