Reputation: 148
I'm writing an adventure game, and I'm writing functions in different files, such as the saveGame
function and read
function. There are 4 main files, all interconnected. The main one is agMain.py
. My issue is that I've imported one of my other files agRead.py
, and call the function within that called read()
. Here is the data for the agRead.py
:
import os
import operator
import sys
import agSave
import agCreation
def read():
while True:
try:
file = open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
break
break
file = open("agData.txt", "r")
data = file.readlines(0)
encrypFName = data[0]
encrypSName = data[1]
encrypAge = data[2]
encrypGender = data[3]
encrypHealth = data[4]
encrypMaxHealth = data[5]
encrypArmour = data[6]
encrypMaxArmour = data[7]
encrypHealthPotions = data[8]
encrypExp = data[9]
encrypMaxExp = data[10]
encrypLevel = data[11]
encrypGold = data[12]
encrypMaxGold = data[13]
encrypPowerLevel = data[14]
encrypMaxPowerExp = data[15]
encrypPowerExp = data[16]
encrypStage = data[17]
fName = encrypFName.strip()
sName = encrypSName.strip()
age = encrypAge.strip()
gender = encrypGender.strip()
health = encrypHealth.strip()
maxHealth = encrypMaxHealth.strip()
armour = encrypArmour.strip()
maxArmour = encrypArmour.strip()
healthPotions = encrypHealthPotions.strip()
exp = encrypExp.strip()
maxExp = encrypMaxExp.strip()
level = encrypLevel.strip()
gold = encrypGold.strip()
maxGold = encrypMaxGold.strip()
powerLevel = encrypPowerLevel.strip()
maxPowerExp = encrypMaxPowerExp.strip()
powerExp = encrypPowerExp.strip()
stage = encrypStage.strip()
As you can see, it sets variables such as stage
and level
. My agMain
files however:
import os
import operator
import sys
import agSave
import agRead
while True:
agRead.read()
if (stage == 1):
exec(open("agStage1.py").read())
elif (stage == 2):
exec(open("agStage2.py").read())
elif (stage == 3):
exec(open("agStage3.py").read())
elif (stage == 4):
exec(open("agStage4.py").read())
elif (stage == 5):
exec(open("agStage5.py").read())
elif (stage == 6):
exec(open("agStage6.py").read())
elif (stage == 7):
exec(open("agStage7.py").read())
elif (stage == 8):
exec(open("ageStage8.py").read())
elif (stage == 9):
exec(open("agStage9.py").read())
elif (stage == 10):
exec(open("agStage10.py").read())
elif (stage > 10):
for i in range(100):
print("Game over!")
print("****************")
print("Well done, you have completed the game!")
exit()
else:
print("An error has occured.")
continue
As you can see here, it uses the stage
when it from the function in the code. But it can't. If I run this, it says stage is not defined, like I hadn't run the function. Is it possible to set variables in a function, use the function, and use the variables in creates in a different file?
EDIT
At the time I made this, I had no knowledge of classes, so I apologise. Everyone who is having a similar problem (sharing variables between functions) just make a class with the functions you want as methods. It saves a lot of hassle!
Upvotes: 1
Views: 57
Reputation: 37003
You need to understand a little more about scoping. Inside a function, names that are bound by an assignment statement are created in the local namespace of the function call. This namespace is created when the function call is made and initialised with the values of the parameters bound to their names. When the function returns (or raises an exception) the namespace is deleted, and the names are no longer available.
Since you want to read lots of different values, consider creating an instance of a class. Instances also have a namespace, and names bound in that namespace will continue to be available until deleted or until the object is garbage collected.
After @Merlin published his helpful answer I decided to update this answer to include a data-driven version, reproduced below (but not tested). Thinking about this might lead you to a function that can create/initialise several different types of object.
Since execution speed is unlikely to be an issue I preferred an approach that was more generalised.
class Conf(object):
pass
def read():
while True:
try:
file = open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
break
break
file = open("agData.txt", "r")
conf = Conf()
names = ["fName", "sName", "age", "gender", "health", "maxHealth",
"armour", "maxArmour", "healthPotions", "exp", "maxExp",
"level", "gold", "maxGold", "powerLevel", "maxPowerExp",
"powerExp", "stage"]
for name in names:
setattr(conf, name, next(file).strip()
return conf
Upvotes: 1
Reputation: 25639
By using chaining, you can reduce the number of lines used and increase readability.
class Conf(object):
pass
def read():
while True:
try:
file = open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
break
break
file = open("agData.txt", "r")
data = file.readlines(0)
conf = Conf()
conf.fName = data[0].strip()
conf.sName = data[1].strip()
conf.age = data[2].strip()
conf.gender = data[3].strip()
conf.health = data[4].strip()
conf.maxHealth = data[5].strip()
conf.armour = data[6].strip()
conf.maxArmour = data[7].strip()
conf.healthPotions = data[8].strip()
conf.exp = data[9].strip()
conf.maxExp = data[10].strip()
conf.level = data[11].strip()
conf.gold = data[12].strip()
conf.maxGold = data[13].strip()
conf.powerLevel = data[14].strip()
conf.maxPowerExp =data[15].strip()
conf.powerExp = data[16].strip()
conf.stage = data[17].strip()
return conf
Upvotes: 1
Reputation: 148
Okay, so I have worked this out. Thanks to everyone who answered, but holdenweb and nightcrawler especially. I have created a class in the agRead.py, and put all of the variables as a part of that class, before returning the class. Here is my agRead.py now:
import os
import operator
import sys
import agSave
import agCreation
class Conf(object):
pass
# READ FUNCTION
def read():
try:
open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
file = open("agData.txt", "r")
data = file.readlines(0)
encrypFName = data[0]
encrypSName = data[1]
encrypAge = data[2]
encrypGender = data[3]
encrypHealth = data[4]
encrypMaxHealth = data[5]
encrypArmour = data[6]
encrypMaxArmour = data[7]
encrypHealthPotions = data[8]
encrypExp = data[9]
encrypMaxExp = data[10]
encrypLevel = data[11]
encrypGold = data[12]
encrypMaxGold = data[13]
encrypPowerLevel = data[14]
encrypMaxPowerExp = data[15]
encrypPowerExp = data[16]
encrypStage = data[17]
conf = Conf()
conf.fName = encrypFName.strip()
conf.sName = encrypSName.strip()
conf.age = encrypAge.strip()
conf.gender = encrypGender.strip()
conf.health = encrypHealth.strip()
conf.maxHealth = encrypMaxHealth.strip()
conf.armour = encrypArmour.strip()
conf.maxArmour = encrypArmour.strip()
conf.healthPotions = encrypHealthPotions.strip()
conf.exp = encrypExp.strip()
conf.maxExp = encrypMaxExp.strip()
conf.level = encrypLevel.strip()
conf.gold = encrypGold.strip()
conf.maxGold = encrypMaxGold.strip()
conf.powerLevel = encrypPowerLevel.strip()
conf.maxPowerExp = encrypMaxPowerExp.strip()
conf.powerExp = encrypPowerExp.strip()
conf.stage = encrypStage.strip()
return conf
and my agMain.py:
# Main
# Will open a stage depending on the stage the user is at.
import os
import operator
import sys
import agSave
import agRead
#Read the file
while True:
agRead.read()
if (conf.stage == 1):
exec(open("agStage1.py").read())
elif (conf.stage == 2):
exec(open("agStage2.py").read())
elif (conf.stage == 3):
exec(open("agStage3.py").read())
elif (conf.stage == 4):
exec(open("agStage4.py").read())
elif (conf.stage == 5):
exec(open("agStage5.py").read())
elif (conf.stage == 6):
exec(open("agStage6.py").read())
elif (conf.stage == 7):
exec(open("agStage7.py").read())
elif (conf.stage == 8):
exec(open("ageStage8.py").read())
elif (conf.stage == 9):
exec(open("agStage9.py").read())
elif (conf.stage == 10):
exec(open("agStage10.py").read())
elif (conf.stage > 10):
for i in range(100):
print("Game over!")
print("****************")
print("Well done, you have completed the game!")
exit()
else:
print("An error has occured.")
continue
And this works perfectly, thank you everyone! This is an amazing community, and I hope to become a real member of it! Thanks again!
Upvotes: 0
Reputation: 22021
Yes it's possible, but variable would be available only after function execution:
### file agRead.py ###
def read():
# some code there
read.my_super_var = 'value'
### file agMain.py ###
import agRead
agRead.read()
print(agRead.read.my_super_var) # value
Upvotes: 0
Reputation: 2456
The variables are only visible from inside read
.
Contain the variables you want to use by doing something like this.
agRead.py
class Conf(object):
pass
def read():
while True:
try:
file = open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
break
break
file = open("agData.txt", "r")
data = file.readlines(0)
encrypFName = data[0]
encrypSName = data[1]
encrypAge = data[2]
encrypGender = data[3]
encrypHealth = data[4]
encrypMaxHealth = data[5]
encrypArmour = data[6]
encrypMaxArmour = data[7]
encrypHealthPotions = data[8]
encrypExp = data[9]
encrypMaxExp = data[10]
encrypLevel = data[11]
encrypGold = data[12]
encrypMaxGold = data[13]
encrypPowerLevel = data[14]
encrypMaxPowerExp = data[15]
encrypPowerExp = data[16]
encrypStage = data[17]
conf = Conf()
conf.fName = encrypFName.strip()
conf.sName = encrypSName.strip()
conf.age = encrypAge.strip()
conf.gender = encrypGender.strip()
conf.health = encrypHealth.strip()
conf.maxHealth = encrypMaxHealth.strip()
conf.armour = encrypArmour.strip()
conf.maxArmour = encrypArmour.strip()
conf.healthPotions = encrypHealthPotions.strip()
conf.exp = encrypExp.strip()
conf.maxExp = encrypMaxExp.strip()
conf.level = encrypLevel.strip()
conf.gold = encrypGold.strip()
conf.maxGold = encrypMaxGold.strip()
conf.powerLevel = encrypPowerLevel.strip()
conf.maxPowerExp = encrypMaxPowerExp.strip()
conf.powerExp = encrypPowerExp.strip()
conf.stage = encrypStage.strip()
return conf
and agMain.py
import agRead
while True:
conf = agRead.read()
if conf.stage == 1:
Upvotes: 0
Reputation: 85767
https://docs.python.org/3/tutorial/controlflow.html#defining-functions:
More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables cannot be directly assigned a value within a function (unless named in a global statement), although they may be referenced.
Assigning to a variable in a function implicitly creates a local variable in that function, unless you've declared it as global
.
Upvotes: 1