How to use single global variable for multiple Python files - python-3.x

I am making a small game in python and I have created 3 python files:
1st file vars.py is intended to store global variables. Let's say it contains single variable and nothing else:
runGame = True
2nd file my_events.py should handle game events and is using vars.py.
from vars import *
def game_events():
global runGame
runGame = False
3rd file myGame.py is a main game file. It contains main game loop and uses variable from vars.py as well:
#I am using this form of import to make it easier to refer to runGame variable
from vars import *
from my_events import game_events
def game_loop():
global runGame
while runGame:
game_events()
game_loop()
quit()
I would assume that when I run myGame.py the program ends as the value of runGame variable is changed to False during first game_loop() cycle when the game_events() is called. But it seems the runGame in myGame.py is not the same that the runGame in my_events.py. So how do I make a variable that is global to all 3 files and when its value changes it affects them all? Or is this a totally wrong approach? (I read that global variables are evil but I don't know how to avoid them in some cases.)

In order to do this, you need to avoid overwriting the variable name with a new value. You can do this by importing the module instead of the variable.
import vars as v
v.runGame = False
If you tweak your code to exclusively modify and access the runGame variable like this, you'll get the "global variable" behavior you'd expect. Otherwise, when you do the assignment in file 1, you're only overwriting what the name runGame means in that file, not what the original variable is.

Related

Reason for error when using exec() within a function in python

If I make a code like:
lists = ["a='1'", "b='2'", "c=a+b"]
returned_list = []
for x in lists:
exec(x)
print(c)
It works, and It print "12". but, If I use exec() in function:
lists = ["a='1'", "b='2'", "c=a+b"]
def test(lst):
for x in lists:
exec(x)
print(c)
test(lists)
It returns NameError: name 'c' is not defined. How could I use exec() in function?
When you assign a new variable in a function, you are actually assigning a variable in a scope which will be closed after the function is closed.
Imagine it as a bubble with an item inside, which after the bubble blows, the item blows and disappears as well. It means, using exec() in a function would create a temporary local variable. But since functions have a predefined code, adding new variables to them without changing the code directly, would not be possible. in that case we need to use global keyword for each new variable in exec to make the variable save in the main and not in function. Therefor, your list would like this:
lists = ["global a\na='1'"]
also I'm not quite sure if you like the output of a+b be 12, if not, you can just remove the single quotes around each number such as "a=1" to make them integers
for further information check this and this

Changing value and importing - Doesn't save new value

I'm using latest python version; I have a simple function in one file, then another file calls that function. Problem is the variable from function isn't printed.
file1.py:
var = "one"
def first():
global var
if smt == True:
var = "1"
else:
var = "W"
file2.py:
from file1 import *
first()
print(var)
This is simplified version because I have more irrelevant code, but the problem is still the same, my variable doesn't change for some reason.
The practice of using import * is usually discouraged; due to the fact that it might be prone to namespace collisions, inefficient if the import is huge et cetera.
I would personally go for an explicit import: from file1 import first
I also believe that you have the wrong idea of what global is. This might help:
In the first case the global keyword is pointless, so that is not
correct. Defining a variable on the module level makes it a global
variable, you don't need to global keyword.
The second example is correct usage.
However, the most common usage for global variables are without using
the global keyword anywhere. The global keyword is needed only if you
want to reassign the global variables in the function/method.
Keep in mind that you do not have var in file2.py by simply using global keyword; if you'd like to access the variable var you can use something like:
In file1.py:
var = "one"
def first():
global var
var = "1"
In file2.py:
import file1
file1.first()
print(file1.var)

Set/Modify the variable used in a function from imported module

Consider following code:
##testing.py
namespace = "original"
def print_namespace():
print ("Namespace is", namespace)
def get_namespace_length(_str = namespace):
print(len(_str))
##Main
import testing
testing.namespace = "test"
testing.printnamespace()
testing.get_namespace_length()
print_namespace() return 'test' as exepcted, but the get_namespace_length() still return 8 which is the length of 'original'. How can I make get_namespace_length() taking the modified variable?
The use case of such implementation is some functions are used the same variable in the imported module, if I can modify/set variable, I can avoid explicitly to call out new variable in each function. Can someone advise?
Also, it doesn't have to be implemented in the way shown above, as long as it works. (global variable etc.)
Um... your default argument for get_namespace_length is database, undefined in your code snippet, also you switch from calling testing to test (I'm guessing that was one of many typos).
In short though, I believe its to do with how the bytecode is compiled in python. Arguments are 'preloaded', and therefore a change to a variable (such as namespace) does not get included in the compilation of get_namespace_length. If I remember correctly, upon import the entire code of the imported file is compiled and executed (try putting a print() statement at the end of testing.py to see)
So what you really want to do to obtain your length of 4 is change testing.py to:
namespace = "original"
def print_namespace():
print ("Namespace is", namespace)
def get_namespace_length():
_str = namespace
print(len(_str))
Or just print(len(namespace)).
Hope that helps!

How do I insert a file into a string? (python3)

I have been trying to make a program that requires reading from a file and then making the string inside the file part of a string in the program. I have written an example of what I do:
gameinfo = [0,0]
def readsave(savefile):
"Reads a file and adds its statistics to variables"
filename = savefile
with open(filename) as file_object:
gameinfo = file_object.readlines()
print(gameinfo)
readsave('gamesave.txt')
print (gameinfo)
But whenever I run this code, all I seem to get is:
['thisworks\n', '7']
[0, 0]
The [0,0] string is what I am trying to change to ['thisworks\n, 7'], however it only changes inside the function. Is there any way which I can make this change global?
The problem here is scope, the gameinfo variable in the function is a local, not a global. You can declare it global, or pass gameinfo around as a parameter. Generally, I avoid global declarations as they can get confusing. I'd recommend passing gameinfo around:
def readsave(savefile, gameinfo=[0,0]): # Declare it as a default to the function.
"Reads a file and adds its statistics to variables"
with open(savefile) as file_object: # No need to rename this.
gameinfo = file_object.readlines()
return gameinfo # Return it so it escapes the scope of this function.
gameinfo = readsave('gamesave.txt') # Save it.
print(gameinfo) # Print it.
Variables are not shared in functions which means you define gameinfo = [0,0] but you are never actually getting that variable in the function. I you want to save in gameinfo you need to use return or global. global will make it possible to share variables inside the function and outside however this is considered bad practice so don't use it.
To use return simply put it in your function. Always make sure you have only one variable, string, integer returning once per call.
Here is your example rewritten to include the return statement I mentioned above:
gameinfo = [0,0]
def readsave(savefile):
"Reads a file and adds its statistics to variables"
filename = savefile
with open(filename) as file_object:
gameinfo = file_object.readlines()
print(gameinfo)
return gameinfo
gameinfo = readsave('gamesave.txt')
print (gameinfo)
You have also made a few other mistakes:
"Reads a file and adds its statistics to variables" is not a comment. Use """my text here""" (triple quotes) or #my text here to insert comments.
All these things you will learn as you read the Python tutorial. Here is one illustrating the use of return.

Declaring variables in a python tkinter button on click command

i am trying to figure out a problem i'm having with declaring a variable upon a button click. For instance i wish to assign to the variable f the value True. I seem to be having trouble with the syntax or method of using the Button function to declare the variable. Do i initialize the variable beforehand? im not quite sure
here is my code:
import tkinter
from tkinter import *
root=Tk()
b1=Button(root,text="test", command=lambda: f=True)
b1.pack()
root.mainloop()
In Python, assignment is a statement, and thus cannot be done with simple lambdas, which can only contain expressions (function calls, variables, attributes, ... not statements, returns1, breaks, ...). To do what you're wanting to do, you must define a normal function as so:
f = False
def onclick():
global f
f = True
This will access the global namescape's f, (use nonlocal if you're within another function) and use that variable within the function. By assigning to this you will change its value in the outer scope.
Note that you must have f defined in the outer scope before the function can reassign it.
To use it, set the command to onclick as such:
b1=Button(root,text="test", command=onclick)
A lambda isn't necessary as you're passing the function object
Note that the function definition must occur before it is passed as the command argument to the new Button
1: By this I mean returning from an outer function, not returns within the lambda, as the entire lambda expression itself is returned.

Resources