Changing value and importing - Doesn't save new value - python-3.x

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)

Related

How to get the var declared in test1.py into test2.py, perform some operation on var in test2.py and get the updated value of var in test1.py?

Assigning value to global var
For Example:
test1.py:
global var
var= 0
def func1():
print("The updated value of var is :"+var)
#after the updated value perform some operation on var
var=var*2
def func3():
global var
print("The final value of var is :"+var)
test2.py:
from test1 import *
def func2():
global var
print("The initial value of var is :"+var)
var = 2+3
func1()
I intend to have the the following values of var:
the initial val of var in func1 of test2.py: 0
The updated value of var in func2 of test1.py: 5
The final value of var in func3 of test1.py: 10
The first thing i notice in your code is the
global var
on the first line. In python this is not needed. Any variable declared in the global scope is automatically global. You'd only need the global keyword inside of a function wanting to modify a global variable.
Another thing which you need to know about python is that a global var is only global for that specific file. It does not transfer over to other modules.
So now: how do you do what you want to do.
The only real way to keep this kind of state across modules i think, is to use some sort of container. Ill use a class but i'm sure things like a dict or a list would work fine. This way you also don't mess up the global scope as much, you can do this for multiple variables in one container, and you don't need the global keywords. This is the case because by importing test1 from test2, you would set var to 0 again as the whole test1 module is executed again. By is resolved by putting this shared container in a third module imported from both test1 and test2. I called this module "shared". The code would look like this:
test1.py:
from test2 import func2
from shared import SharedContainer
def func1():
print("The updated value of var is: {}".format(SharedContainer.var))
# after the updated value perform some operation on var
SharedContainer.var = SharedContainer.var*2
def func3():
print("The final value of var is: {}".format(SharedContainer.var))
if __name__ == "__main__":
func2()
func3()
test2.py
from shared import SharedContainer
def func2():
from test1 import func1
print("The initial value of var is: {}".format(SharedContainer.var))
SharedContainer.var = 2+3
func1()
shared.py
class SharedContainer:
var = 0
Hope it helps :)

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.

How to use single global variable for multiple Python files

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.

Call a function dynamically from a variable - Python

Ok so I have two files, filename1.py and filename2.py and they both have a function with same name funB. The third file process.py has function that calls function from either files. I seem to be struggling in calling the correct function.
In process.py:
from directoryA.filename1 import funB
from directoryA.filename2 import funB
def funA:
#do stuff to determine which filename and save it in variable named 'd'
d = 'filename2'
# here i want to call funB with *args based on what 'd' is
So i have tried eval() like so:
call_right_funB = eval(d.funB(*args))
but it seems not to work.
Any help is appreciated.
The problem is, you can't use eval() with a combination of a string and a method like that. What you have written is:
call_right_funB = eval('filename'.funB(*args))
What you can do is:
call_right_funB = eval(d + '.funB(*args)')
But this is not very pythonic approach.
I would recommend creating a dictionary switch. Even though you have to import entire module:
import directoryA.filename1
import directoryA.filename2
dic_switch = {1: directoryA.filename1, 2: directoryA.filename2}
switch_variable = 1
call_right_funB = dic_switch[switch_variable].funB(*args)
Hope it helps.

Resources