Java and Python print variables differently

I study the scope of variables and looked at 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 UnBoundLocalError: local variable 'c' referenced before assignment 1 2 and UnBoundLocalError: local variable 'c' referenced before assignment . When I translated it 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(); } } 

Prints 1 2 3 . I'm sure I translated it correctly (very embarrassing if it is not). My question is why is Python giving an error, but Java is not? Is this somehow related to different coverage or the way they are interpreted and compiled?

+4
source share
4 answers

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

 c = c + 1 

in foo makes c local variable, therefore

 print c 

tries to print an unrecognized local variable and throws an exception.

Java has variable declarations. Your Java code declares c outside of main and does not update it inside, so Java knows that c is a static variable and the program works. The best translation of Python code in 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(); } } 
+4
source

The misunderstanding and surprise that you had, like many people learning Python (do research on stackoverflow.com with the expression "refered before assign"), I concluded that the documentation is sometimes poorly written.

The explanation of this error is here:

If the name binding operation occurs anywhere inside the code block, all use of the name inside the block is considered as a reference to the current block. This can lead to errors when the name is used in before binding it. This rule is subtle. Python lacks a declaration and allows you to perform name binding operations anywhere inside the code block. The local variables of the code block can be determined by scanning the entire text of the block to bind the name of the operation.

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

In my opinion, this passage poorly expresses what is executed when the code is executed:
" can be determined by scanning" is deceptive, it seems that this scan is optional.

Although I never read anything about this that would confirm my opinion, I personally think that:
- in fact, this IS scan has always been performed, which is not an option - more importantly, this scan is performed before any call to the called object that defines the block

.

In fact, it is important to understand the first:

definition of the called object is performed before the object can be called

It should be understood that the term "definition" is ambiguous, since it can be understood in two ways:
1 / definition = code block in a script that “defines” something
2 / definition = execution of this code block at the moment of script execution to create a specific called object

I base these apertures on:

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

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

.

A function definition defines a custom function object (...)
The definition of a function [meaning 1] is an executable statement. Its execution binds the name of the function in the current local namespace for the function object (...)
The definition of a function [meaning 2] does not fulfill the function body; this is done 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 ANYTHING. I find it more useful to analyze what follows:
[meaning 1], “definition” means “code block (= text) that defines”
[sens 2], "definition" means "the execution of the defining code block"; the text (the meaning of Definition 1) does nothing, it passively lies like text ...

You see that the name "definition" is ambiguous, and the document is sometimes poorly written ...

The last passage refers to function definitions, but these concepts can obviously be extended to classes and other called objects. Classes are also defined by code blocks, and then these two steps exist for them: definition (meaning 2 = execution of the defining code block), and then a call.

.

So, I argue that I am founded to think that scanning identifiers in the called object and determining their areas is performed at the moment when the code block [= definition 1] is executed, and this execution is the so-called "definition" [meaning 2] .
This is what I would like to point out as a key point in my opinion.

.

PS: the use of the term “variable” in the above document extract is deplorable, because “variable” is another very ambiguous term when used in Python.
It is regrettable that the OP presents its question by comparing what is happening in Java and what is happening in Python.
If somewhere in the base official document there was a solid explanation for the fact that in Python, the encoder does not have access to objects that act as a "piece of memory, the contents of which may change," such confusion should rarely occur. But this other story

+3
source

Python checks the local scope for variables and, if it has not been declared or specified in the local scope, it searches for higher scopes. Using c=c+1 in a function, Python sees c in the local area and throws an error when trying to print, because it is not declared. If you remove c=c+1 , it should print c. To get the behavior you expect, put global c inside your function.

Note: it is usually not recommended to use global variables, so pythonic alternates may consist in passing the variable as an argument to the function, or if what you do is suitable for the classes, makes the variable self.

eg.

 class myclass: def __init__(self): self.a = 1 self.b = 2 self.c = 3 def count(self): print self.a print self.b print self.c self.c = self.c + 1 def main(): thing = myclass() thing.count() thing.count() main() 

gives

 nero@ubuntu :~/so$ python -i so.py 1 2 3 1 2 4 >>> 
+1
source

I think the confusion lies in the fact that although Python is an interpretation language, it analyzes the whole area of ​​functions. See Examples:

 >>> a=1;b=2;c=3 >>> def foo(): ... print a, b, c #c refers to the c in the outer scope ... >>> foo() 1 2 3 >>> >>> def foo(): ... print a, b, c #c refers to the local c defined later ... c = 2 ... >>> foo() 1 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in foo UnboundLocalError: local variable 'c' referenced before assignment >>> 

In Python scope rules, you can reference LEGB

+1
source

Source: https://habr.com/ru/post/1491234/


All Articles