Trying To Recreate An SICP Example In Python
home // page // Trying To Recreate An SICP Example In Python

Trying To Recreate An SICP Example In Python

This morning I was playing around and decided to try and recreate an example from Structure and Interpretation of Computer Programs (SICP). Along the way I discovered some unexpected gotchas with how Python scopes closures. The example I was trying to reproduce was the following one:

Initially, thinking that Python 2.7.x closures were pretty good in my experience, I decided on the following naive implementation:

But when you hop in the Python shell and try to run this you’ll have the following experience:

After digging around for a little bit I found this excellent article containing some gotcha’s regarding scoping in Python closures. To quote (with some edits for our example):

…When you say [balance = balance + amount], two things happen at different times:

1. When Python compiles the function, it sees [balance] =, and declares a new variable, scoped within inner, named [balance].

2. When Python executes the function, it needs to compute [balance + amount]. Okay, well, what’s [balance]? It’s a local variable… but, oops, it doesn’t have a value yet! Raise error.

The assignment creates a new inner variable that masks the outer variable

Luckily, Python 3 fixes the issue by introducing the nonlocal keyword, but in Python 2.X the solution is a bit hacky:

This works because Python leverages 3 different types of assignment, the regular = assignment, __setattr__ assignment, and __setitem__ assignment. The original = assignment attempted to created a new variable, but by triggering __setitem__ assignment instead we get the expected behavior.

Hopefully this will help stop others from getting tripped up on this.

Resources To Better Understand The Issue: