Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java and Python printing variables differently

Tags:

java

python

scope

I am learning about variable scoping and was looking through some threads when I saw the following Python code:

a = 1
b = 2
c = 3

def foo():

    print a
    print b
    print c
    c = c + 1

def main():

    foo()

main()

which prints out 1 2 and UnBoundLocalError: local variable 'c' referenced before assignment. When I translated this to Java

public class Test1 {

static int a = 1;
static int b = 2;
static int c = 3;

public static void foo()
{
    System.out.println(a);
    System.out.println(b);
    System.out.println(c);
    c = c + 1;
}   

public static void main(String[] args)
{
    foo();
}   
}

It prints out 1 2 3. I am pretty sure I translated it correctly(highly embarrassing if it isn't). My question is why does Python give an error whereas Java does not? Is it something to do with different scoping or the way that they are interpreted and compiled?

like image 588
Nestle Crunch Avatar asked Jan 13 '23 22:01

Nestle Crunch


2 Answers

Python has no variable declarations. Instead, it defines a rule that any name you assign to in a function is a local variable of that function. That means that the line

c = c + 1

in foo makes c a local variable, so

print c

tries to print an unassigned local variable and raises an exception.

Java has variable declarations. Your Java code declares c outside main and doesn't redeclare it inside, so Java knows that c is a static variable, and the program works. A better translation of the Python code to Java might be

public class Test1 {

    static int a = 1;
    static int b = 2;
    static int c = 3;

    public static void foo() {
        int c; // Now c is local, like in the Python
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        c = c + 1;
    }   

    public static void main(String[] args) {
        foo();
    }   
}
like image 181
user2357112 supports Monica Avatar answered Jan 22 '23 20:01

user2357112 supports Monica


The incomprehension and astonishment you had, like many people learning Python (do a research on stackoverflow.com with "referenced before assignment" expression), me comprised, is due to the fact that the documentation is sometimes badly written.

The explanation of this error is here:

If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.

http://docs.python.org/2/reference/executionmodel.html

In my opinion, this extract badly expresses what is performed when a code is executed:
saying "can be determined by scanning" is deceiving, it gives the impression that this scanning is optional.

Though I've never read anything about this point that would have confirmed my opinion, I personnaly think that:
- in fact this scanning IS always performed, that's not an option
- more importantly, this scanning is done before any call of the callable object that the block is defining

.

Indeed, there's an important notion to understand first:

the definition of a callable object is done before the object can be called

One must realize that the term "definition" is ambiguous because it can be understood in two ways:
1/ definition = code block in a script that "defines" something
2/ definition = the execution of this code block at the moment of the execution of the script to create the defined callable object

I base these asertions on:

A block is a piece of Python program text that is executed as a unit. The following are blocks: a module, a function body, and a class definition.

http://docs.python.org/2/reference/executionmodel.html

.

A function definition defines a user-defined function object (...)
A function definition [sense 1] is an executable statement. Its execution binds the function name in the current local namespace to a function object (...)
The function definition [sense 2] does not execute the function body; this gets executed only when the function is called.

http://docs.python.org/2/reference/compound_stmts.html#function-definitions

.

A function definition defines a user-defined function object : such a beautiful tautology ! This sentence explains NOTHING. I think more useful to analyze what follows:
[sense 1] there, "definition" means "the code block (=text) that defines"
[sens 2] there, "definition" means "the execution of the defining code block"; a text (definition sense 1) doesn't execute anything, it passively lies as a text...

You see that the name "definition" is ambiguous and the doc is sometimes badly written.....

The last extract concern functions definitions but the notions can evidently be extended to classes, other callable objects. Classes are also defined by code blocks and then these two steps exist for them too: definition (sense 2= execution of the defining code block) and then call.

.

So my claim is that I'm founded to think that the scanning of the identifiers in a callable object and the determination of their scopes is performed at the moment the code block [= definition sense 1] is executed, this execution being so called "definition" [sense 2] too.
That's what I wanted to point out as the key point in my opinion.

.

PS: the use of the term "variable" in the above extract of the doc is deplorable, because "variable" is another highly ambiguous term when used in Python.
The proof it is deplorable is that the OP presents his question doing comparison of what happens in Java and what happens in Python.
If there were somewhere in the basic official doc a solid explanation of the fact that in Python the coder has no access to entities acting as "chunk of memory whose content can change" , this kind of confusion should more rarely happen.
But that's another story

like image 39
eyquem Avatar answered Jan 22 '23 19:01

eyquem