Python doesn't provide a block scope. The minimum scope for a variable is the function (like it happens in pre-ES6 Javascript).
The original reason for this design (if I understood correctly) is that if you need block-scope variable then the code is probably too complex anyway and factorizing out a function is a good idea (note that you can create local functions/closures in Python so this doesn't necessarily mean the code will need to be spread and delocalized like it would happen with C).
As an exception to this "no-block-scope" rule, with Python3 variables used inside comprehensions were made local to the comprehension, i.e. after
x = [i*i for i in range(10)]
i
will be 9 in Python2, but no variable i
will leak from the expression in Python3.
Python rules for scoping are not very complex: if there are assignments (or augmented assigments like +=
-=
and so on) in the body of the function then the variable is considered a local, if instead it's only accessed for reading the variable is considered coming from an outer scope (or a global if the function is at top level).
If you need to modify a global in a function (not something that should happen often) you need to declare it explicitly with global
.
In Python3 it's also possible to access a local variable captured in an inner function for writing by using a nonlocal
declaration. In Python2 instead captured local variables can only be accessed for reading in inner functions (assignment would make them locals of the inner function and global
declaration would make them globals instead).