Initialize variable in loop - use global variable? - python

I wrote a function that makes a screenshot and checks if it's different than the old one. The example code is below. However, I wonder about pythons best practice to set the variables oldimage and image. Especially oldimage needs to be set before main() can start the first time. Do I use global variables?
def main():
image=screenGrab()
if equal(image,oldimage):
pass
else:
dosomething()
oldimage=image
while True:
main()

Using global variables is almost never the correct solution. It usually ends up causing more problems than solutions. Continuing from #MartijnPieters, I would organize your code as follows:
def main():
oldimage = loadLastImage()
while True:
image=screenGrab()
if not equal(image,oldimage):
dosomething()
saveLastImage(image) # this is the opposite of loadLastImage()
oldimage=image
# this is the more accepted way of running main
# because it still allows your code to be loaded as module
if __name__ == "__main__":
main()

Related

Why not place if __name__ == '__main__' at the beginning of the module?

Why is it standard in Python to have the main() function and the if __name__ == '__main__' check at the end of the block of code? It also seems standard for the abstraction of the functions to follow the same pattern upwards. What I mean is that the definition of the function to be executed by main() is above the main() and the definition of the functions inside that are above and so on..
That seems odd because when one opens the module to read the code, it ends up starting with low-level code and moves up to higher level functions. Isn't it hard to grasp what the module is doing that way?
Why not do the alternative? Have the if __name__ check at the top followed by the main() function, and so on. This way, one quickly glances at what the main() function does and understands what the code is about.
You can't call main() before it is defined. And main cannot call other functions before they are defined.
Example 1:
if __name__=='__main__':
main()
def main():
print("Hello")
This will error because main hasn't been defined yet at the point where you try and execute it.
Example 2:
def main():
hello()
if __name__=='__main__':
main()
def hello():
print("Hello")
This will error because main() is executed and tries to call hello before it is defined.
The if __name__=='__main__': which contains the call to main() works best at the end of the file so that everything that it needs has been defined before it is reached.
Where you put the main definition itself is more flexible, but putting it at the end (just before the if __name__=='__main__': block that calls it) makes as much sense as anywhere else.
The purpose of an if __name__ == '__main__': guard is to prevent a module from having side-effects when it's imported.
The fact that it is a module rather than a script implies that it will normally be used by other code importing the definitions from it, not executed directly. So given that, it makes sense that the functions, classes and constants appear first in the source code, since those are what users of the module will be importing (and hence, what they might want to see the source of).
So even if the code guarded by if __name__ == '__main__': doesn't rely on the definitions in the module already having been evaluated (which would be unusual), this part of the code is usually the least important to the users of the module, so it doesn't belong at the start of the file.

Communication between two python programs

please help me understand why this doesn't work and how to change it.
I basically want to be able to query values of a var of program one from program two. So here are the most basic programs:
P1:
import time
gscore = 0
def get_info():
return gscore
def main():
global gscore
score = 0
while score <10:
time.sleep(1)
score +=1
gscore = score
print(score)
if __name__ == '__main__':
main()
P2:
from functest import get_info
print(get_info())
The structure may seem a bit weird but basically I have an existing small python game and want to be able to query the score which is why I adapted it in this way. So P1 obviously counts to ten but P2 always gets 0 as a return value. I feel like I'm making a really stupid mistake here...
Thx for help :)
if __name__ == '__main__' is only executed when you run your code form a shell and not when you import your program from another program. To fix this you can modify your program as:
In you P1 modify get_info to this:
def get_info():
global gscore
return gscore
In your P2 do this:
from functest import main, get_info
main()
print(get_info())
Also, note that there are better way of doing what you are doing like using a class instead of creating a global variable.
class Score(object):
def __init__(self, gscore=0):
self.gscore = gscore
def get_info(self):
return self.gscore
def increment(self, score=0):
while score < 10:
score +=1
self.gscore = score
When you import a module in Python you are not executing the content of it.
if __name__ == "__main__": is there so that your Python files can act as either reusable modules, or as standalone programs.
If you want to execute the main() function you'll need to explicitly call it.:
from functest import main, get_info
main() # calling the main function in your functest file
print(get_info()) # calling the get_info function
this will return the value you are looking for.
Now, main will be called if you execute the functest.py file:
$ python functest.py
#=> 9
When you import a function of another program, you are importing the functionality of the program, not the actual instance of the program. What I mean by that is that your program only counts to 10 while it's running, but 10 isn't part of the code, it's a result.
What importing it allows you to do is run the bit of code you imported (In your case, running the get_info code with the gscore = 0 being the gscore that is returned, however, this is a distinct instance of your other program, so even if gscore is increasing in another program that you're running with the main method, your second program has it's own gscore that is 0. Importing is more for when you have a sort of library of functions in a program that you want access to.
What you want is to be able to, run time, read a value that the other program has generated. This can't be done with python variables, but it can be done in many other ways. A common way is to write the score to a file, then read the file in your other program. If you need information on how to read and write files, read this guide here.

Python __name__() main function

I have tried looking for an answer online but couldn't find it. I am fairly new to python and wondering if you could have multiple main function in a program. For example:
ask_user = int(input('enter your choice (1 or 2): '))
if ask_user == 1:
def print_hello():
print('hello world')
def main():
print_hello()
if __name__ == '__main__': main()
elif ask_user == 2:
def print_hi():
print('hi')
def main():
print_hi()
if __name__ == '__main__': main()
Is this a good programing practice?
This wouldn't be considered good programming practice, no. Like index.html, the point of main() is to have a primary entry point to the program. Even if a particular language allowed that sort of thing, it would be confusing for anyone reading the code and trying to figure out where to start. For the display options, you would use separate functions with meaningful names, such as print_hello_world and print_hi, and they would both be able to be called by main().

Function not changing global variable

my code is as follow:
done = False
def function():
for loop:
code
if not comply:
done = True #let's say that the code enters this if-statement
while done == False:
function()
For some reason when my code enters the if statement, it doesn't exit the while loop after it's done with function().
BUT, if I code it like this:
done = False
while done == False:
for loop:
code
if not comply:
done = True #let's say that the code enters this if-statement
...it exits the while loop. What's going on here?
I made sure that my code enters the if-statement. I haven't run the debugger yet because my code has a lot of loops (pretty big 2D array) and I gave up on debugging due to it being so tedious. How come "done" isn't being changed when it's in a function?
Your issue is that functions create their own namespace, which means that done within the function is a different one than done in the second example. Use global done to use the first done instead of creating a new one.
def function():
global done
for loop:
code
if not comply:
done = True
An explanation of how to use global can be found here
done=False
def function():
global done
for loop:
code
if not comply:
done = True
you need to use the global keyword to let the interpreter know that you refer to the global variable done, otherwise it's going to create a different one who can only be read in the function.
Use global, only then you can modify a global variable otherwise a statement like done = True inside the function will declare a new local variable named done:
done = False
def function():
global done
for loop:
code
if not comply:
done = True
Read more about the global statement.
Using a class rather than global:
Another way to handle (not use) global variables is to wrap the functions and variables you wish to be global in a class.
While this is a little heavy for this specific case - classes add a host of functionality and flexability to the project. (Personally) highly recommended.
For example:
class Processor():
"""Class container for processing stuff."""
_done = False
def function(self):
"""A function which processes stuff."""
# Some code here ...
self._done = True
# See the flag changing.
proc = Processor()
print('Processing complete:', proc._done)
proc.function()
print('Processing complete:', proc._done)
Output:
Processing complete: False
Processing complete: True

Why is the main() function not defined inside the if '__main__'?

You can often see this (variation a):
def main():
do_something()
do_sth_else()
if __name__ == '__main__':
main()
And I am now wondering why not this (variation b):
if __name__ == '__main__':
do_something()
do_sth_else()
Or at least this (variation c):
if __name__ == '__main__':
def main():
do_something()
do_sth_else()
main()
Of course the function calls inside main() might not be function calls, they just represent anything you might want to do in your main() function.
So why do people prefer variation a over the others? Is it just style/feeling or are there some real reasons? If possible, please also link sources.
Why limit your main() function to command line usage only?
By defining a main() function at module scope, you can now wrap your script and alter how it is called. Perhaps you want to set default arguments in sys.argv, perhaps you want to reuse the code in another script.
This is because there are two ways of using Python scripts. One from the command line and another when importing it from another script. When you run it from command line, you want to run main() function and when you import it you may not want to run main() function until you need it ( you just want to import main() ).

Categories

Resources