Python Exhibits Behavior Similar to Javascript's Variable Hoisting
Python shows an unexpected behavior in situations where a local variable is defined with the same name as a global variable. Here's an example:
x = 2
def foo():
print x
x = 5
You'd probably expect foo() to print "2" (the value of the global variable 'x'). Instead it throws an error:
UnboundLocalError: local variable 'x' referenced before assignment
The reason for the error is that we're defining a local variable 'x' later in the function. But why would a variable declaration later in the code have any effect?
To get an intuition for what's happening in Python, it's helpful to look at variable hoisting behavior in JavaScript. Here's the parallel code:
var x = 2;
function foo(){
console.log(x);
var x = 5;
}
You'd probably expect foo() to print "2" but instead it prints the JavaScript keyword undefined. Undefined translates as "the variable x has been declared, but has not yet been initialized with a value". This is essentially the same as the Python error, except that in JavaScript undefined is a perfectly legal value.
Here's what's happening. The Javascript interpreter reads the entire function and finds the variable definition. It then moves ("hoists") the variable declaration to the top of the function, while leaving the variable initialization in its original position. So when the function is executed, it's as if the code had been written like this:
var x = 2;
function foo(){
var x; // the hoisted variable declaration
console.log(x);
x = 5;
}
Now it's easy to see that the local variable x already exists when 'x' is referenced in the console.log() function. That explains why the value of the global x isn't printed. And since the local x has not yet been assigned a value when console.log() is called, its value is undefined.
This is the same situation we're seeing in the Python example. The interpreter is aware that a local variable x exists, but it is complaining because x has not yet been assigned a value. The situation is harder to understand in Python, however, because Python lacks the ability to declare variables without assigning them values. Thus while Python's internals are different than JavaScript's, understanding JavaScript variable hoisting may help make Python's behavior a little less mystifying.