Name binding and UnboundLocalError in Python

Yesterday I ran into a silly error which wasn’t very obvious at first, so I thought I’d share. It happened after renaming some module imports, here is the code and the traceback:

[gist]https://gist.github.com/1028793[/gist]

As you can see, there is a module called hostand also a local variable called the same used in a for loop. Then why does Python think the first use of the host variable is done before its assignment? The answer can be found here in the Python reference guide. Let me highlight an important paragraph:

If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.

This means that because the host variable is assigned in the function, no matter where in the function, its scope is that function, and the global scope is not taken into account. One could think that adding global host at the top of the function would solve it. But that is plain wrong. If you do that, the host module will be overwritten by the last value of the host variable after iterating the for loop.

Then how do we solve it? There is no way to do it in Python 2.X, just change the name of either the imported module or the local variable. In Python 3 the nonlocal keyword can be used, as pointed out here.

:wq

Leave a Reply

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