4

I'm a bit confused with the variable scope of Python. Perhaps because of being used to the convention of C++, I always made some mistakes in variable scope of Python. For example:

in C++:

int main(){
    int i = 3;
    for (int j = 0; j <= 3; ++j){
        i += 1;
    }
    cout << "i = " << i << endl;
    cout << "j = " << j << endl; //Error, out of 'for' scoping.
    return 0;
}

But in Python:

i = 3
for j in range(1,4):
    i += 1
print j               # j = 3, nothing wrong
for i in range(5,7):
    j += 1
print i               # i = 6, changed by operation in for loop

This is just a simple example, and I'm not going to list other differences. Could anyone please give a detailed explanation of their differences in scoping.

TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
user123
  • 231
  • 2
  • 12
  • There are detailed explanations of the python/c++ scoping rules in the official documentation. What part when reading it did you not understand? Surely you don't want us to reiterate everything or copy-paste it. – timgeb Jan 25 '16 at 07:04
  • After both loops, the loop variable has the last value it was given. You comment claiming some difference is wrong. – Terry Jan Reedy Jan 25 '16 at 07:09
  • Hi, @timgeb, I didn't find the corresponding part, could you please attach a link? Thank you so much! – user123 Jan 25 '16 at 07:11
  • Read the tutorial at least up the the point where it starts discussing the stdlib modules. Basically, the module is a scope, each class and function is a new scope, blocks are not scopes. – Terry Jan Reedy Jan 25 '16 at 07:13
  • Somehow your question shortens to: How not to do the same error again and again? The answer is simple: concentration and focus. – Klaus D. Jan 25 '16 at 07:16
  • Did you try Googling, say, "python scope"? – TigerhawkT3 Jan 25 '16 at 07:31
  • Good idea, thanks for reminding! – user123 Jan 25 '16 at 14:35

2 Answers2

4

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).

6502
  • 112,025
  • 15
  • 165
  • 265
0

Python distinguishes only two variable scopes - local and global.

Global variable is the same like in C/C++, i.e. it's globally accessible and keeps its value cross function calls.

Local variable is local to the function (similar to JavaScript). Any modification inside inner blocks modifies the variable for the whole function scope.

EDIT: Thanks to the comments, I forgot nonlocal statement. This allows referring from inner function to variable from enclosing function, check here for explanation. However it still doesn't allow limiting the scope of the variable to specific block.

Community
  • 1
  • 1
Zbynek Vyskovsky - kvr000
  • 18,186
  • 3
  • 35
  • 43
  • There also captured variables in closures, normally read-only for syntax reasons but can also be made read-write (with Python3 only) by the `nonlocal` declaration. – 6502 Jan 25 '16 at 07:13
  • This is wrong. Python allows access to variables from containing scopes. In Python 3.x, you can even use [the `nonlocal` statement](https://docs.python.org/3/reference/simple_stmts.html#nonlocal) to explicitly refer to a variable from an outer scope (see [PEP 3104](https://www.python.org/dev/peps/pep-3104/) for details). – taleinat Jan 25 '16 at 07:14
  • 1
    @6502: You're right about `nonlocal`, but actually it solves the other problem - referring to outer scope function. Basically it doesn't introduce new type of scope. – Zbynek Vyskovsky - kvr000 Jan 25 '16 at 07:21
  • 1
    @ZbynekVyskovsky-kvr000: it depends how you define scope. A captured variable is a local but a local of someone else: inside a function you have locals, locals of someone else (captured) and globals (and also comprehension iteration variables in Python3). – 6502 Jan 25 '16 at 07:29