Python class and global vs local variables

I have a problem understanding what is happening with the result of the following code snippets:

my_str = "outside func" def func(): my_str = "inside func" class C(): print(my_str) print((lambda:my_str)()) my_str = "inside C" print(my_str) 

Output:

 outside func inside func inside C 

Another piece of code:

 my_str = "not in class" class C: my_str = "in the class" print([my_str for i in (1,2)]) print(list(my_str for i in (1,2))) 

Output:

 ['in the class', 'in the class'] ['not in class', 'not in class'] 

The question arises:

  • What happens here in every print () statement?
  • Can someone explain why the print () operator gets a string from different namespaces?

Change 1:

I think this is different from this question , because I humbly think that the answers there do not explain this variation:

 my_str = "outside func" def func(): my_str = "inside func" class C(): print(my_str) print((lambda:my_str)()) #my_str = "inside C" print(my_str) 

Output:

 inside func inside func inside func 

Edit 2:

Indeed, this is a duplicate of this question , because, as Martin Peiters says:

The answer states: if the name is assigned inside the body of the class, almost at the very beginning. You assigned my_str, doing the same thing as there. Commenting out this line means that you no longer assign to my_str, which makes it the same case as x.


+6
source share
1 answer

There are four areas here:

  • global area
  • scope
  • class body
  • lambda area

When creating a class operator, the class body is executed as a function, and the local namespace of this function is used as class attributes.

However, the body of the class is not a scope and, as a result, behaves differently than functions. In the body of a function, a binding defines an area; assign a name to the function and it is marked as local. In a class, assigning a name makes it global until you actually complete the task.

So, your first call to print() finds my_str as global, because later in the class of the class you are bound to a name. This is a consequence of the fact that class bodies do not participate in regions.

Then you define the lambda and call it. my_str never assigned in this lambda, so it needs to be found in the parent scope. Here, the class body is not a scope, and the next scope is the scope. This is why this line prints inside func .

Finally, you assign the local name my_str in the body of the class and print this local.

At the time the assignment is deleted, names in the class are considered non-local; the first and last print() statements are now equal, and the name is simply looked up according to the usual scope rules.

+5
source

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


All Articles