4

How does scope sharing in python work?:

def test():
    if True:
        a = 3
    print a

This question has been asked in several ways, several times, but what is the reason, that python is not so strict about scopes? The same code in C++ would yield the error:

error: 'a' was not declared in this scope
Aswin Murugesh
  • 10,831
  • 10
  • 40
  • 69
user1767754
  • 23,311
  • 18
  • 141
  • 164
  • Because there is no need for declaration. It's WHERE you assign the name that counts, scope-wise, whereas the content defines its type (which can therefore change over time...) – Pynchia Nov 03 '15 at 07:16
  • So it will just lookup where in the hierarchy it will find the value? So variables are not destroyed after leaving the scope? – user1767754 Nov 03 '15 at 07:17
  • http://stackoverflow.com/q/291978/238978 – Emil Vikström Nov 03 '15 at 07:18
  • @EmilVikström i read this article, but it's overloaded with too much info – user1767754 Nov 03 '15 at 07:19
  • yes, of course objects are garbage-collected. Read about namespaces. Understanding python names, scope and typing is VERY important. – Pynchia Nov 03 '15 at 07:20
  • Are you asking *why* python doesn't have the same scoping rules as C++, or *what* those rules are? It isn't clear. – juanchopanza Nov 03 '15 at 07:22
  • 1
    There is no "hierarchy" in your example, the scope of a single function is flat despite the nesting levels. A name showing up *anywhere* in the function definition is equivalent to it being "declared" at the top of the function and assigned wherever it is first assigned to. (The normal "hierarchy" of scopes is fixed: a function, module, built-in. The only way to define a true hierarchy of scopes is with nested functions.) – user4815162342 Nov 03 '15 at 07:48
  • *what is the reason, that python is not so strict about scopes?* Because Guido made it that way? – kylieCatt Nov 03 '15 at 07:55
  • @Pynchia Technically, it doesn't count *where* you assign: assignment *anywhere* in the function body behaves as if an unbound local variable was declared at the beginning of the functions. This becomes visible when you try to assign to a global later in the function, as shown [here](http://pastie.org/10526495), and is a [frequent point of confusion](https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value) with Python beginners. – user4815162342 Nov 03 '15 at 11:56
  • @user4815162342 oh, yes, of course. I never meant to say one line is better than another. I meant within a scope-block/namespace (i.e. module, function, ...) – Pynchia Nov 03 '15 at 13:41
  • @Pynchia Right, you even said "scope-wise", I missed that bit. – user4815162342 Nov 03 '15 at 14:19

2 Answers2

4

In C++ each set of braces defines a new scope, but that's not true of Python and indentation levels. In Python only the function and module define scope; control blocks like if do not.

Adam
  • 16,808
  • 7
  • 52
  • 98
2

The reason behind Python's scope sharing rules is a consequence of Python's choice not to have explicit declarations of local variables. Without such declarations, C++-style scoping rules where every nesting creates a new scope would make the following fail:

def test():
    if some_condition:
        a = 3
    else:
        a = 5
    # If the above nesting created a new scope, "a" would
    # now be out of scope.
    print a

That works in C++ because explicit declarations provide you with choice between writing:

// doesn't work
if (some_condition) {
    int a = 3;
}
else {
    int a = 5;
}
// "a" is out of scope
std::cout << a ;

and:

// works
int a;
if (some_condition) {
    a = 3;
}
else {
    a = 5;
}
printf("%d\n", a);

Python, having no explicit declarations for local variables, must extend the scope to the whole function definition (and class definition in case of class scope).

user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • So why is `a` restricted to the function's scope? – juanchopanza Nov 03 '15 at 07:25
  • @juanchopanza Because a function, unlike an ordinary indented block, does create its own scope. It would be confusing and dangerous to create global variables automatically automatically all over the place. Also, if/where one wants them, one **does** have the option of using the `global` declaration. – user4815162342 Nov 03 '15 at 07:29
  • Because that's the typical use case. If you need to write to a global, you have to explicitly ask for it. There *are* languages where the default is to create globals (JavaScript, Lua), but that is often a source of bugs. – Matteo Italia Nov 03 '15 at 07:30
  • (interestingly, both JavaScript and Lua provide their own twist: Lua requires a `local` declaration to create local variables, and then enforces proper block scoping; JavaScript requires `var` for locals, but still does variable hoisting, providing as usual the worst of all worlds :o) ) – Matteo Italia Nov 03 '15 at 07:35
  • Obviously a function creates a scope, otherwise there would be no scope for `a` to be restricted to. The point is your answer ("...Python has no explicit variable declarations...") doesn't explain why a function has a scope and an if statement doesn't. – juanchopanza Nov 03 '15 at 07:36
  • @juanchopanza The answer explains why `if` doesn't introduce a new scope ("why is Python not so strict..."), which is what the OP asked. It is obvious why a function has a scope - to prevent all variables in the program from being global. Where in the OP's question do you see the implication of your question? – user4815162342 Nov 03 '15 at 07:39
  • Sorry, but even assuming your interpretation of the question, I don't see how your answer explains why an `if` statement doesn't introduce a new scope. – juanchopanza Nov 03 '15 at 07:57
  • @juanchopanza Because it would then be impossible to introduce a variable in different branches of `if`, which is a common use. This is explained in the answer and supported by concrete Python and C++ (pseudo-)examples. If you still consider it unclear, do you have a suggestion how to make it more clear? – user4815162342 Nov 03 '15 at 10:16