Reputation: 145
Heyo, I've run upon a problem. So I have three files:
And I want the Main Program to call a function from the Functions module, which changes a variable in Data. Then I need to use the new variable elsewhere in the Main Program.
This is what I want, shown as a simplified demonstration program:
The Data file:
#data.py
#just an short depiction of my actual file
text = ""
The Functions file:
#functions.py
from data import *
def printHi():
global text
text = "hi"
print(text)
The Main Program:
#mainProgram.py
from functions import *
from data import *
printHi()
print(text)
What I expected would happen would be that when I run the Main Program:
The Functions file and Data file is imported.
Then it calls the "printHi" method from the Functions file.
The variable "text" from the Data file is assigned "hi", and is printed.
The the Main Program prints the "text" variable.
And I supposed that the text variable would be "hi". However, to my disappointment, it prints blank. It does indeed print the initial text value.
I really have NO idea why this is so. Shouldn't the text variable have already been changed? Could you please explain what part about my program is wrong and how to correct it?
Upvotes: 2
Views: 1088
Reputation: 3892
Cool, we have a lot of people saying "don't do this!". Well, what should you do then? The good way to do this is to pass the text variable into the function and out of it. Like so:
The Data file:
#data.py
#just an short depiction of my actual file
text = ""
The Functions file:
#functions.py
from data import *
def printHi(atext):
atext = "hi"
print(atext)
return atext
The Main Program:
#mainProgram.py
from functions import *
from data import *
text = printHi(text)
print(text)
That solves your problem. You should probably also get rid of the * imports as the other answer suggests but that's a philosophical question.
Upvotes: 2
Reputation: 54273
The short answer is simply not to do this. It's a Bad Idea for all the reasons that global variables are always bad ideas: because they lead to stack overflow questions that read like "If I do this thing I shouldn't do, it does something I didn't expect -- why did it do that?" Whose easiest answer is, as you've now read, "That's why you shouldn't do that thing."
The long answer is a bit beyond me without spending a whole lot more time on the matter, but the longer answer is simple enough. When you do those "star" imports (from modulename import *
) you're rebinding the name of the variable. What functions.printHi
thinks of as text
is not data.text
but actually functions.text
. When it's changed in printHi
, it changes functions.text
which should still be okay, since mainProgram
is also importing functions
.
However remember that mainProgram
ISN'T actually importing functions
, it's from functions import *
'ing. That means what mainProgram
thinks of as text
is neither data.text
nor functions.text
, but mainProgram.text
. When functions.printHi
changes functions.text
, it doesn't touch mainProgram.text
.
The short answer applies here because these sorts of pitfalls are non-obvious unless you can think deeply enough about your code to understand them. If you are able to think that deeply about your code, you should be able to write something that can sidestep such pitfalls entirely. For instance: "global mutable state" is generally a bad thing. Avoid it.
To just make this work, drop all your "star" imports. The following code works:
# functions.py
import data
def printHi():
# plus! You don't need the `global` anymore.
data.text = "hi"
print(data.text)
# mainProgram.py
import functions
import data
functions.printHi() # prints "hi" from inside functions.printHi
print(data.text) # also prints "hi"
Upvotes: 3