Python class variable vs normal function variables global scope

zazas321

Joined Nov 29, 2015
926
Hello. I have recently started learning python and trying to understand classes and their scope. I have come from C,C++ background therefore I am used to a little bit different programming.

Please check the code below and help me understand it:

Code:
class test:
test4 = 0
def __init__(self,ID,Serial,Quantity):
self.ID = ID
self.Serial = Serial
self.Quantity = Quantity
#creating class constructor
obj = test(1,2,3)

def function_outside_class():
print("test1=",obj.ID)
print("test2=",obj.Serial)
print("test3=",obj.Quantity)
print("test4=",obj.test4)
obj.ID = 123
obj.test4 = 444
print("modified obj.ID outside class=",obj.ID)
print("modified obj.test4 outside class=",obj.test4)
#Function inside function
function_inside_function_outside_class()

def function_inside_function_outside_class():
print("test1 inside function=",obj.ID)
print("test2 inside function=",obj.Serial)
print("test3 inside function=",obj.Quantity)
print("test4 inside function=",obj.test4)
obj.ID = 999
obj.test4 = 888
print("modified obj.ID outside class in another function=",obj.ID)
print("modified obj.test4 outside class in another function=",obj.test4)

function_outside_class()
So I have created a class test. I have made a constructor as following:
obj = test(1,2,3)

My main question is:
How Is it possible that I am allowed to modify variables inside that class within nested functions without declaring it as global or without even declaring it inside the functions that are using the class?
The results below prove that I am able to modify class variables without any declaration:
Code:
test1= 1
test2= 2
test3= 3
test4= 0
modified obj.ID outside class= 123
modified obj.test4 outside class= 444
test1 inside function= 123
test2 inside function= 2
test3 inside function= 3
test4 inside function= 444
modified obj.ID outside class in another function= 999
modified obj.test4 outside class in another function= 888
The second experiment I have made is just declaring a normal variable as global inside function as following:

Code:
def test2():
global test5
test5 = 1
print("test5=",test5)

def modifying_test2_outside_function():
test5 = 12
print("modified test5=",test5)
function_inside_function()

def function_inside_function():
#global test5  THIS IS REQUIRED TO MODIFY TEST5 INSIDE THIS FUNCTION
print("modified test5=",test5)
test5=123
print("twice modified test5=",test5)
The results:
Code:
test5= 1
modified test5= 12
Traceback (most recent call last):
File "/home/pi/Desktop/lukas_programming/PTL_python/clas test.py", line 54, in <module>
modifying_test2_outside_function()
File "/home/pi/Desktop/lukas_programming/PTL_python/clas test.py", line 46, in modifying_test2_outside_function
function_inside_function()
File "/home/pi/Desktop/lukas_programming/PTL_python/clas test.py", line 49, in function_inside_function
print("modified test5=",test5)
UnboundLocalError: local variable 'test5' referenced before assignment
As you can see I can modify the test5 variable without declaring it inside function modifying_test2_outside_function but I cannot modify it when I use nested functions. For that, I need to declare it inside function_inside_function()

My third question would be:
Is it okay to use python classes as a struct alternative to C or C++? For example if I have multiple flag variables I would normally set them global ( if using in interrupts, timers and etc) as following:
Code:
global flag_button, flag_switch, flag_timer
If I use this approach and I am trying to acess these flags in nested functions, I would need to declare them seperately as seen in my 2nd experiment. That is not very convenient I believe.

However, as we seen from the 1st experiment with classes, I could create a class "flags", create my flag variables there and that would allow me to access those variables anywhere in my code without the need of declaration as following:
Code:
class flags:
def __init__(self,button,switch,timer):
self.button = button
self.switch = switch
self.timer = timer

or even?

class flags:
button = 0
switch = 0
timer = 0
def __init__(self,button,switch,timer):
pass

flags_class = flags()
Now with the declarations above, I can access those 3 flag variables anywhere in my code without any declaration:
Code:
flags_class.button = 1 #
SET THE button flag to 1

I am hoping that some of you will be able to help me understand how these things work exactly! I appreciate any help!

vanderghast

Joined Jun 14, 2018
55
I am not knowledgeable in Python, but in APL, from which Python derives.

For the scopes. Consider C++ scopes.

int i = 1;
int j= 2;
{
int i = 3;
int k = 9;
// here, i = 3 and j = 2 and k =9
}
// here, i = 1, j = 2 and k is undefined.

Note how j percolated through the simple { } while i would have done the same, if it had not been re-declared. The new declaration of i "hides" the first declaration.

In APL, objects always percolate, all over the place, like the Sun delivering its warm all over the place. The only way to block the Sun is to ... blocking it, if that is what you need. Or using object so while you have access to the object, you may not have a direct access to the manipulation of its properties. Arguments of procedures, with a name, always block the name they use (so recursion is naturally available), be careful, if you give the name Sun to one of your argument, then, that procedure doesn't reference (directly) to the real world, the global, Sun, but whatever is behind the blocking name Sun. In Debug mode, you may be surprised to see that Sun value is 3, while you expect it to be 1, and with a few clicks, still in Debug, the Sun comes back to 1... like the variable i, here up, could do.