Page 1 of 1
Structured prog & global variables
Posted: Tue May 07, 2019 6:28 am
by Roffey
In my ignorance I don't know if this is hardware specific or not. Using an ESP32 spiram.
I have a main program which is getting a little messy, so I have started to use extra files which have function def's in. In the main program I 'import from' so I can use them.
All goes well until I want to manipulate variables which have been declared in the main file. All that I have read indicates that if I declare the variables as 'global' within the external function, before I use them, then they can be accessed.
Well, whatever I do, I get errors thrown up, in that the variable is not recognised.
I would appreciate any guidance here ….. I have done my best in terms of searching … but to no avail.
As a second related question, I have also got a socket (udp) set up in the main program, which retrieves sent data. This all works fine.
In the same 'external' function with the global variable issue, I would like to refer to the socket for sending data out. This also fails.
All works well if I place the function back in the main section, but it would be nice to structure the program in a more orderly fashion.
Thanks for any help.
D.R.
Re: Structured prog & global variables
Posted: Tue May 07, 2019 10:03 am
by OutoftheBOTS_
It is best if possible to avoid global variables where possible.
The cleanest way to have many functions access a common variable is to use a class and then use the prefix self. before any variables that you want to be accessible from all the other functions/methods of the class.
see
https://www.tutorialspoint.com/python/p ... bjects.htm
Re: Structured prog & global variables
Posted: Tue May 07, 2019 11:06 am
by Roffey
Thank you for that …. still learning.... only a few years to go!
Off to do some reading then.
Thanks again
Re: Structured prog & global variables
Posted: Thu May 09, 2019 5:47 am
by pythoncoder
The advice about avoiding globals is undoubtedly correct. Access is relatively slow. But there are other reasons rooted in general programming practice which you can research online.
It's worth understanding Python's scoping rules. If a module has a global name (whether for data or for an object such as a function) the name's visibility to other modules depends on how the module is imported.
my_module:
Code: Select all
import my_module
my_module.foo() # Access by prepending the module name
my_module.bar = 99
print(my_module.foo()) # 99
Code: Select all
from my_module import foo
foo()
bar = 99 # Will create a new variable local to the current module
print(foo()) # Will return 42
The need for a global statement arises if a function needs to modify a global variable. Consider the following
Code: Select all
bar = 42
def foo():
global bar
bar = 99
Without the global statement
foo() would create a local variable
bar and set that to 99 leaving the global
bar unchanged: in other words
foo() would do nothing useful. For some reason when I was learning Python this took me a while to grasp.
There is an option to import all exposed names from a module with
This should be used with care as it can populate your local namespace with unexpected names and can be a source of evil bugs (say if the author has redefined a Python built-in function). Only use if you understand the module you're importing.
Re: Structured prog & global variables
Posted: Thu May 09, 2019 7:31 am
by Roffey
Thanks for taking the time ….. these snippets really help get a better understanding ….
Re: Structured prog & global variables
Posted: Thu May 09, 2019 9:15 am
by JumpZero
Hello,
We know that using global variables isn't a good practice. But it's sometimes convenient and Python permits it.
However I was recently surprised to find that global variables are global to a module not across all modules. Reading the doc teachs me this is normal behavior. So that's ok when you know it, and one more reason to avoid "global" or at least to be (very) careful.
Exemple tested on Python3 on PC and microPython 1.10 on ESP32
Code: Select all
>>> def foo():
... global bar
... bar = bar + 1
... return bar
...
...
...
>>> bar = 5
>>> foo()
6
>>>
Now we define the same function but in a module:
my_module.py :
Code: Select all
def foo():
global bar
bar = bar + 1
return bar
Code: Select all
>>> import my_module
>>> bar = 5
>>> my_module.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "my_module.py", line 3, in foo
NameError: name 'bar' isn't defined
>>>
Re: Structured prog & global variables
Posted: Thu May 09, 2019 4:22 pm
by pythoncoder
Actually this is a strength of Python. If you issue
you have a guarantee that the only name added to your namespace is
my_module: names within the module a guaranteed not to conflict with your own because you have to prepend them with the module name:
Code: Select all
import my_module
x = my_module.foo()
Likewise if you issue
you know exactly which names you've added. Issuing
will populate your namespace with an arbitrary assortment of names. This can have unforeseen consequences. It has its uses, but you need to study the module code.
This is the sort of chaos which your truly global variables might unleash
Re: Structured prog & global variables
Posted: Thu May 09, 2019 4:34 pm
by dhylands
JumpZero wrote: ↑Thu May 09, 2019 9:15 am
Now we define the same function but in a module:
my_module.py :
Code: Select all
def foo():
global bar
bar = bar + 1
return bar
Code: Select all
>>> import my_module
>>> bar = 5
>>> my_module.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "my_module.py", line 3, in foo
NameError: name 'bar' isn't defined
>>>
Your my_module.py file should rather contain:
Code: Select all
bar = 0
def foo():
global bar
bar = bar + 1
return bar
and then if you wanted to change the global, you'd do:
Code: Select all
>>> import my_module
>>> my_module.bar = 5
>>> my_module.foo()
6
Re: Structured prog & global variables
Posted: Fri May 10, 2019 3:50 pm
by JumpZero
Hi!
Actually very interesting discussion.
@dhylands you are right the proper way to access the module global variable "bar" is:
"my_module.bar" this avoids confusion, keeping in mind that the main programme global variable "bar" is another variable.
@pythoncoder Yes this is a Python strength: the guarantee of names being uniques in user's namespace when you prepend them with module name. And thanks to pointing out the risks of using
I didn't realize that. Better be careful and use the full name with module name prepending.
And now for the fun: the unleashed sort of chaos
Code: Select all
jumpzero@penguin:~$ cat my_module.py
bar = 0
def foo():
global bar
bar = bar+1
return bar
jumpzero@penguin:~$ python3
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> bar = 3
>>> bar
3
>>> from my_module import *
>>> bar
0
>>> foo()
1
>>> bar = 7
>>> bar
7
>>> foo()
2
>>> bar
7
>>> foo()
3
>>>