NameError: name 'useraction' is not defined - python

I made sure to have global before main(), and I did assign a value to the variable useraction. Why does it still say it's undefined?
import os.path
from os import path
shoppinglist = []
global useraction
def main():
Displaylist()
RunItemAction()
def Displaylist():
i = 0
if (len(shoppinglist)>0):
while (i<=len(shoppinglist)):
print(shoppinglist[i] +"\n")
i+=1
useraction = str(input("Do you want to add, remove, or search for an item? "))
useraction = useraction.upper()
def RunItemAction():
if( useraction == "ADD"):
AddItem()

I think you should use it like this.
import os.path
from os import path
shoppinglist = []
useraction="" # or any default value you want to give
def main():
Displaylist()
RunItemAction()
def Displaylist():
global useraction
i = 0
if (len(shoppinglist)>0):
while (i<=len(shoppinglist)):
print(shoppinglist[i] +"\n")
i+=1
useraction = str(input("Do you want to add, remove, or search for an item? "))
useraction = useraction.upper()
def RunItemAction():
global useraction
if( useraction == "ADD"):
AddItem()

Any name defined at the global scope is, by definition, global.
The global statement is used in another scope to mark a name that would otherwise be local as global.
import os.path
from os import path
shoppinglist = []
def main():
Displaylist()
RunItemAction()
def Displaylist():
global useraction
i = 0
if (len(shoppinglist)>0):
while (i<=len(shoppinglist)):
print(shoppinglist[i] +"\n")
i+=1
useraction = str(input("Do you want to add, remove, or search for an item? "))
useraction = useraction.upper()
def RunItemAction():
global useraction
if( useraction == "ADD"):
AddItem()
That said, don't use a global variable at all. Pass arguments to functions, and make them return values.

Related

Changing the value of variables in a class through a function outside the class in python

I am trying to modify the value of a variable (in this case an integer) that is located inside of a class using a function that's outside of that class. But when I call the function, the value of the variable us_balance stays the same: 42.
class Country:
us_balance = 42
def buy(country, amount):
if country.lower == "us":
Country.us_balance = Country.us_balance - amount
def stats():
print(Country.us_balance)
while True:
user_input = input("> ").lower()
if user_input == "buy":
amount = input("$ ").lower()
balance_to_set = amount.split()
buy(balance_to_set[0], int(balance_to_set[1]))
if user_input == "stats":
stats()
break
Any ideas on how to fix this?
You should create an instance of the class and pass that in to the various functions. By using Country it is creating a new instance of the class each time and that is why the stats function is reporting 42 as the value.
Here's a example that should work for you.
class Country:
us_balance = 42
def buy(ci, country, amount):
if country.lower() == "us":
new = ci.us_balance = ci.us_balance - amount
ci.us_balance = new
def stats(ci):
print(ci.us_balance)
# Create an instance of the class
ci = Country()
while True:
user_input = input("> ").lower()
if user_input == "buy":
amount = input("$ ").lower()
balance_to_set = amount.split()
buy(ci, balance_to_set[0], int(balance_to_set[1]))
if user_input == "stats":
stats(ci)
break
All I had to do was just add parentheses to the .upper() function in the class

Global variables in multiples functions in Python

i will try to explain my situation with examples:
Im using global to declare a variable but this work only in a function, when i try to another sub function doesnt work.
register.py
def main():
alprint = input("Enter something: ")
if alprint == "a":
def alCheck():
global CheckDot
CheckDot = input("Enter your opinion: ")
def alTest():
global CheckTest
CheckTest = input("Hope it works: ")
alCheck()
alTest()
main()
and content.py
from register import CheckTest
if CheckTest == "ad":
print("You are welcome!")
When i declare this variable checkTest in a sub function(function, alTest()) of main, using global and importing to another file, it doesnt work, i tried a lot of things, but nothing.
It would work, except that if the user enters something other than a for the first input, CheckTest is not defined, so it gives an ImportError. You might want to try something like this instead:
def main():
global CheckTest, CheckDot
def alCheck():
global CheckDot
CheckDot = input("Enter your opinion: ")
def alTest():
global CheckTest
CheckTest = input("Hope it works: ")
alprint = input("Enter something: ")
if alprint == "a":
alCheck()
alTest()
else:
CheckTest = None
CheckDot = None
main()
This way, CheckTest, and CheckDot are always defined.

How to access a dictionary in a function that is defined in another function in the same class

I have created a class with two functions inside of it. These functions run forever in a loop at the bottom of the code. However, the first function creates a dictionary and the user adds values to this dictionary. The second function is meant to import the dictionary and add 10 to each value. However, when I run this code, I get an error stating that 'Materials is not defined'. How am I supposed to properly use the dictionary in both functions?
Here is my code:
class materialsClass:
def materialsChange(self):
while True:
q1 = raw_input("Type 'edit' to add or change a material, or 'continue' to continue: ")
if q1 == 'edit':
while True:
q2 = raw_input("Type 'add' to add a new material, 'edit' to edit amount of a material: ")
if q2 == 'add':
x = str(raw_input("Enter the Material: "))
y = int(0)
Materials = {x:y}
break
elif q2 == 'edit':
x = str(raw_input("Enter your Material: "))
y = int(raw_input("Enter your Change: "))
Materials[x] += y
break
else:
print "Please Type an Option"
elif q1 == 'continue': break
else:
print "Type an Option!"
print Materials
def materialCounter(self):
for k in Materials: Materials[k] += 10
print Materials
while True:
obj=materialsClass()
obj.materialsChange()
obj.materialCounter()
You cannot use a variable local to a method within another method. You need to define the variable in the class scope and make it an instance variable. For example:
class materialsClass:
def __init__(self):
self.Materials = dict()
def materialsChange(self):
...
self.Materials[x] = y
(in place of Materials = {x:y})
def materialCounter(self):
for k in self.Materials:
self.Materials[k] += 10
print self.Materials
Also note that when the interpreter runs the line
Materials = {x:y}
it replaces the Materials dictionary with a new one and you are not actually adding a new material in the dictionary. That's why you should write:
self.Materials[x] = y
instead. This will add a new material to the dictionary.
Variables inside the functions are in local namespace so you can not use Materials inside the second function as it has been defined in first one ! you can initial Materials in the enclosing class scope instead :
But note that you need to initial your variable inside the __init__ function:
class materialsClass:
def __init__(self):
self.Materials=dict()
def materialsChange(self):
while True:
q1 = raw_input("Type 'edit' to add or change a material, or 'continue' to continue: ")
if q1 == 'edit':
while True:
q2 = raw_input("Type 'add' to add a new material, 'edit' to edit amount of a material: ")
if q2 == 'add':
x = str(raw_input("Enter the Material: "))
y = int(0)
self.Materials = {x:y}
break
elif q2 == 'edit':
x = str(raw_input("Enter your Material: "))
y = int(raw_input("Enter your Change: "))
self.Materials[x] += y
break
else:
print "Please Type an Option"
elif q1 == 'continue': break
else:
print "Type an Option!"
print self.Materials
def materialCounter(self):
for k in self.Materials: self.Materials[k] += 10
print self.Materials
To build on some of the other answers. You have to create a dictionary under the class and the way you were adding items to the dictionary was incorrect so I have changed that. You also have to create a class in the proper way for it to work. I have checked this code and it works for me anyway. I hope this helps.
class materialsClass(object):
def __init__(self): # create a new class
self.materials = {} # create a new dictionary under this class
def materialsChange(self):
while True:
q1 = raw_input("Type 'edit' to add or change a material, or 'continue' to continue: ")
if q1 == 'edit':
while True:
q2 = raw_input("Type 'add' to add a new material, 'edit' to edit amount of a material: ")
if q2 == 'add':
x = str(raw_input("Enter the Material: "))
y = int(0)
self.materials[x] = y # this is how to add items to dictionaries sequentially
print self.materials
break
elif q2 == 'edit':
x = str(raw_input("Enter your Material: "))
y = int(raw_input("Enter your Change: "))
self.materials[x] = y
print self.materials
break
else:
print "Please Type an Option"
elif q1 == 'continue': break
else:
print "Type an Option!"
print self.materials
def materialCounter(self):
for k in self.materials:
self.materials[k] = self.materials[k] + 10
print self.materials
obj=materialsClass() # you do not need to create the class again and again, just once is fine
while True:
obj.materialsChange()
obj.materialCounter()

Doing a sort of a loop while avoiding a certain prerequisite (beginner/python)

A beginner's problem, here it goes:
I'm writing a program which keeps records of a game of darts. The user types in the players and their respective scores. It's possible to do a query about a player's scores and ask the program for the best overall score between all the players. I have the following functions:
add_score
return_players_score
return_best_score
exit_program
main
In main(), we begin by creating a new empty dictionary (say, players = {}). Then we ask the user to input a number that takes him/her to the function of choice (1: add_score etc.).
Now, once we're in add_score and have added a key:value pair (player:score), we need to go back to inputting the number taking to the function of choice. I implemented it simply by writing main() to the end of add_score.
That, however, takes us to the beginning, where there's players = {} and thus whatever data we input in add_score gets wiped out. This then affects other functions and the program remains useless as long as it forgets everything right away. How to solve this?
I'd paste the actual code but it's not in English and it's an assignment anyway...
Thanks.
Rather than calling main() from each of your other functions, you should just return (or run off the end of the function, which is equivalent to return None). Since you need the main function to run things repeatedly, you should use a loop.
def main():
players = {}
while True: # loop forever (until a break)
choice = input("what do you want to do (1-4)")
if choice == "1":
add_score(players)
elif choice == "2":
return_players_score(players)
#...
elif choice == "4":
break # break out of the loop to quit
else:
print("I didn't understand that.")
If you have a loop that does something like the following..
example:
while True:
players = {}
some code adding to players
This loop will always reset players to {}
However, if you do:
players = {}
while something:
some code adding to players
then players is not being reset at the start of each iteration through the loop
But your question is not clear
If you have something like this:
def add_score(dicccionary):
#do something with diccionary
main()
def main():
dicccionary = {}
while something:
option = input("option")
if option == 1:
addscore(dicccionary)
else:
#otherfunction
main()
your reset problem can be solve like:
dicccionary = {} #global variable
def add_score():
#do something with diccionary
main()
def main():
option = input("option")
if option == 1:
addscore()
else:
#otherfunction
main()
By the way, you shouldn't make it this way, try something as:
dicccionary = {} #global variable
def add_score():
#do something with diccionary
def main():
while somecondition:
option = input("option")
if option == 1:
addscore()
else:
#otherfunction
main()
If I was doing it for real then I would go for something like:
import sys
class ScoreKeeper(object):
def init(self):
self.scores = {}
def add_score(self, player, score):
self.scores[player] = score
def _print_player_score(self, player, score):
print 'player:', player, 'score:', score
def print_scores(self):
for player, score in self.scores.items():
self._print_player_score(player, score)
def best_score(self):
best, player = 0, "no player"
for player, score in self.scores.items():
if score > best:
best, player = score, player
self._print_player_score(player, best)
if __name__ == '__main__':
scorer = ScoreKeeper()
quit = lambda: sys.exit()
choices = quit, scorer.add_score, scorer.print_scores, scorer.best_score
def help():
print 'Enter choice:'
for index, c in enumerate(choices):
print '%d) %s' % (index, c.__name__)
def get_integer(prompt):
res = raw_input(prompt)
try:
return int(res)
except:
print 'an integer is required'
return get_integer(prompt)
def get_choice():
choice = get_integer('choice? ')
if not 0 <= choice < len(choices):
help()
return get_input()
return choice
help()
choice = get_choice()
while(choice):
args = []
if choices[choice] == scorer.add_score:
args.append(raw_input('player name? '))
args.append(get_integer('score? '))
choices[choice](*args)
choice = get_choice()
quit()

Python dumps variable from loop

Total bottles variable in the getBottles module resets to 0 upon exiting the while counter <8 loop. I've also tried using return statements but to no avail. How do I get the value from totalBottles variable to pass to my other module.
global totalBottles, totalPayout, todayBottles
totalBottles=0 #store the accumulated bottle values
counter=1 #will control the loop
todayBottles=0 #store the number of bottles returned on a day
totalPayout=0 #store the calculated value of totalBottles x.10
def main():
keepGoing='y'
while keepGoing =='y':
getBottles (totalBottles, todayBottles, counter)
calcPayout (totalBottles, totalPayout)
printInfo(totalBottles, totalPayout)
keepGoing == raw_input ('Do you want to run the program again?')
def getBottles (totalBottles, todayBottles, counter):
while counter <8:
todayBottles = input ('Enter number of bottles returned for the day:')
totalBottles = todayBottles + totalBottles
counter=counter + 1
def calcPayout(totalBottles, totalPayout):
totalPayout = totalBottles * .10
def printInfo(totalBottles, totalPayout):
print totalBottles,('is the total bottles')
print totalPayout, ('amount due')
main()
i can't resist... (although there are still issues with this at least it might work where the other won't)
class Bottles:
def __init__(self):
self.totalBottles=0 #store the accumulated bottle values
self.counter=1 #will control the loop
self.todayBottles=0 #store the number of bottles returned on a day
self.totalPayout=0 #store the calculated value of totalBottles x.10
def getBottles(self):
while self.counter <8:
self.todayBottles = input ('Enter number of bottles returned for the day:')
self.totalBottles = self.todayBottles + self.totalBottles
self.counter=self.counter + 1
def calcPayout(self):
self.totalPayout = self.totalBottles * .10
def printInfo(self):
print self.totalBottles,('is the total bottles')
print self.totalPayout, ('amount due')
def main():
keepGoing='y'
while keepGoing =='y':
b = Bottles()
b.getBottles()
b.calcPayout()
b.printInfo()
keepGoing == raw_input ('Do you want to run the program again?')
main()
if you want to use global variables, you have to specify this in the function also :
global totalBottles, totalPayout, todayBottles
totalBottles=0 #store the accumulated bottle values
counter=1 #will control the loop
todayBottles=0 #store the number of bottles returned on a day
totalPayout=0 #store the calculated value of totalBottles x.10
def main():
global totalBottles, totalPayout, todayBottles
keepGoing='y'
while keepGoing =='y':
getBottles (counter)
calcPayout ()
printInfo(totalBottles, totalPayout)
keepGoing == raw_input ('Do you want to run the program again?')
def getBottles (counter):
global totalBottles, todayBottles
while counter <8:
todayBottles = input ('Enter number of bottles returned for the day:')
totalBottles = todayBottles + totalBottles
counter=counter + 1
def calcPayout():
global totalBottles, totalPayout, todayBottles
totalPayout = totalBottles * .10
def printInfo(totalBottles, totalPayout):
print totalBottles,('is the total bottles')
print totalPayout, ('amount due')
main()
otherwise you could use return values :
global totalBottles, totalPayout, todayBottles
totalBottles=0 #store the accumulated bottle values
counter=1 #will control the loop
todayBottles=0 #store the number of bottles returned on a day
totalPayout=0 #store the calculated value of totalBottles x.10
def main():
keepGoing='y'
while keepGoing =='y':
totalBottles = getBottles(totalBottles, todayBottles)
totalPayout = calcPayout (totalBottles)
printInfo(totalBottles, totalPayout)
keepGoing == raw_input ('Do you want to run the program again?')
def getBottles (totalBottles, todayBottles):
counter=1
while counter <8:
todayBottles = input ('Enter number of bottles returned for the day:')
totalBottles = todayBottles + totalBottles
counter=counter + 1
return totalBottles
def calcPayout(totalBottles):
totalPayout = totalBottles * .10
return totalPayout
def printInfo(totalBottles, totalPayout):
print totalBottles,('is the total bottles')
print totalPayout, ('amount due')
main()
Could the problem be scope related? It seems you have declared global variables and then pass them around in your method calls. I wonder if it is confused, using a local totalBottles instead of the global one. Try this without passing around your global variables.
Using global in the global namespace does nothing. If you want to update a global from inside a function, you have to use it there:
def calcPayout():
global totalPayout
totalPayout = totalBottles * .10 # now the global gets updated
You have to do this to all your functions.
The much, much saner way is to use return:
def calcPayout(totalBottles):
return totalBottles * .10
totalPayout = calcPayout(totalBottles)

Categories

Resources