Why does Python have variable hoisting like Javascript?

Hi Géry,

“However, C++ outputs 1 in both cases, as expected.”

Expected by who? Not me. Why does C++ behave so strangely?

"What was the rationale of the Python language designers for choosing

variable hoisting?"

I have never heard of “variable hoisting” before, but if this is it:

"Variables declared using var are created before any code is executed in

a process known as hoisting. Their initial value is undefined."

then Python doesn’t have it. It’s certainly not a term commonly used in

Python. Python is not like Javascript, it doesn’t not create variables

before the code runs.

(Although some Python interpreters, not all, may sometimes allocate

space for local variables at runtime, when the function object is

created, before it is called.)

Your Python code:


def f():

    print(x)



x = 1

f()

Here x is a global variable. Inside the function f, the scope of the

names “print” and “x” are both global, so when you call the function,

the builtin print function and the global variable x are both found.


def f():

    print(x)

    x = 2



x = 1

f()

Here x is a local variable, and you try to print its value before

x exists, so you get an UnboundLocalError exception.

When the compiler is compiling a function, read-only access to a name

like “print” or “x” uses the global and builtin scopes. But if you

assign a value to a name, then the compiler treats it as a local

variable unless you declare it global.

So in your example above, the name “print” is read but not written to,

so it is looked for in the global scope and the builtin print

function is located and called.

The name “x” is written to (with the “x = 2” assignment) so the

compiler treats it as a local variable. At lookup time, the variable

doesn’t yet exist and so you get an exception.

The global statement is a compiler directive: it tells the compiler to

treat the name as a global variable, even if it otherwise would have

been treated as a local.


def f():

    global x

    print(x)

    x = 2



x = 1

f()

will print 1 and then assign 2 to the global variable x.

You can google for “Python scoping rule LEGB” for more information:

https://duckduckgo.com/?q=python+scoping+LEGB+rule

Why does Python work this way? I don’t know, why does any language

choose the scoping rules they choose?

Why does Lua default to having variables be global unless declared

local? Why does Javascript have a separate global and module scope? Why

does BASIC have only global variables? (1970s BASIC, not modern Visual

Basic.)

People design their languages to work the way they want them to work. I

imagine the same applied to Python: Guido chose the scoping rules

because they were easy to implement, or similar to what ABC used, or

because they solved a problem, or because he liked that rule and

disliked more complicated rules, or something like that.

“This counterintuitive behaviour of Python”

Counter-intuitive to who? It is perfectly intuitive to me, and the C++

behaviour seems strange even after you explained it.

"and Javascript is also known

as variable hoisting since it ‘hoists’ variable declarations (but

not definitions) at the beginning of their blocks."

Python doesn’t have declarations, with the possible exception of the

global and nonglobal statements. (I personally consider them to be more

like compiler directives than a declaration.) But in any case, in both

of your examples of Python code, there are no variable declarations, so

there is nothing to be hoisted.

1 Like