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)
Related
I have to create this program for a class. I have been reading in various posts that lists in Python are already global and can be used in def statements.
Here are some of the resources I found that said this:
How to define a global list in python and append local list to it
How to declare python global list
Python global lists
None of these solutions have helped me and I am currently trying to figure this out. I might just have to rewrite it so that it doesn't use "options...". I also have a lot of "\n"s to make it look like it scrolls away from the old outputs because the teacher doesn't want to see them.
Here is the code I am having an issue with:
#!/usr/bin/python
import sys
def Switcher():
selec = 0
while (1):
print "\n\n\n\n\n\n\n\n\n\n\n\n\n"
print "\n==== WELCOME TO SPACECODE'S BANK ===="
print "==== Select an Option: ====\n"
print " 0. Check Current Balance\n"
print " 1. Deposit Money\n"
print " 2. Withdraw Money\n"
print " 3. Transaction History\n"
print " 4. Exit\n"
options = {0: zero,
1: one,
2: two,
3: three,
4: four
}
selection = input("\n")
if (selection < 0) or (selection > 4):
print '\n'
else:
selec = selection
options[selec]()
def zero():
global current
print "\n\n\n\n\n\n\n\n\n\n\n\n\n"
print "\n==== YOUR CURRENT BALANCE: ====\n"
print current
raw_input("\n Press enter to continue....")
Switcher()
def one():
print "\n\n\n\n\n\n\n\n\n\n\n\n\n"
global current, i
print "\n==== INPUT DEPOSIT AMOUNT: ====\n"
add = input()
current = add + current
i =+ 1
transact.append(i)
account.append(current)
raw_input("\n Press enter to continue....")
Switcher()
def two():
print "\n\n\n\n\n\n\n\n\n\n\n\n\n"
print "\n==== INPUT AMOUNT TO WITHDRAWL: ====\n"
global current, i
temp = current
wdrw = raw_input()
if (temp == 0):
print "==== YOU DONT HAVE ANY MONEY TO WITHDRAWL ====\n"
Switcher()
elif ((temp - wdrw) < 0):
print "==== YOU CANT WITHDRAWL MORE THAN YOU HAVE IN BALANCE ====\n"
two()
elif ((temp - wdrw) >= 0):
i =+ 1
transact.append(i)
current = temp - wdrw
account.append(current)
print "\n==== TRANSACTION SUCCESSFUL ====\n"
raw_input("\n Press enter to continue....")
Switcher()
def three():
global i
print "\n\n\n\n\n\n\n\n\n\n\n\n\n"
print "\n ==== TRANSACTION HISTORY (SAVES LAST 30) ====\n"
for w in range(len(trasac)):
print(transac[w]," : ",account[w])
print()
raw_input("\n Press enter to continue....")
Switcher(current)
def four():
sys.exit()
account = []
current = 0
transac = []
i = 0
Switcher()
Is it perhaps because you are declaring transac = [] instead of transact = [] at the bottom of your code?
I have been using global variables for a little text game in python and have come across a lot of articles saying that global variables are a no no in python. I have been trying to understand how to get what I have below (just a health variable and being able to change it and print it) working using classes but I am confused how I can converted something like this in a class. Any help, example, point in the right direction would be great.
Here is an example of me using variables.
import sys
import time
health = 100
b = 1
def intro():
print("You will die after two moves")
def exittro():
time.sleep(1)
print("Thanks for playing!")
sys.exit()
def move():
global health
global b
health -= 50
if health <= 51 and b >0:
print("almost dead")
b = b - 1
def death():
if health == 0 or health <= 0:
print("...")
time.sleep(1)
print("You died\n")
time.sleep(2)
print("Dont worry, this game sucks anyway\n")
exittro()
intro()
a = 1
while a == 1:
input("Press Enter to move")
move()
death()
Thank you
Edit: this is the kind of thing I have been trying to do...
class Test:
def __init__(self):
number = 100
def __call__(self):
return number
def reduceNum(self):
number -=10
def printNum(self):
print(number)
a = 1
while a == 1:
input("Enter")
Test.self.reduceNum()
Test.self.printNum()
I would avoid classes for this, as classes are generally slower. You could make the function return the new value for the health variable.
I would also suggest making a main controller function to take the return value and apply it to other functions. This prevents global variables outside of a function's scope.
import time
def intro():
print("You will die after two moves")
def outro():
time.sleep(1)
print("Thanks for playing!")
# sys.exit() # You can avoid this now by just stopping the program normally
def move(health):
health -= 50
if health <= 51:
print("almost dead")
return health # Return the new health to be stored in a variable
def death(health):
if health <= 0:
print("...")
time.sleep(1)
print("You died\n")
time.sleep(2)
print("Dont worry, this game sucks anyway\n")
return True # Died
return False # Didn't die
def main():
health = 100 # You start with 100 health
intro()
while not death(health):
# While the death function doesn't return `True` (i.e., you didn't die) ...
input("Press enter to move")
health = move(health) # `health` is the new health value
outro()
If you want to use classes, you need to actually instantiate the class (Make a new object from it) by doing instance = Test(). You also need to store variables as attributes of self (so self.number = number) as any local variables are different from each other.
class Test:
def __init__(self):
self.number = 100
def __call__(self):
return self.number
def reduceNum(self):
self.number -= 10
def printNum(self):
print(self.number)
a = 1
game = Test()
while a == 1:
input("Enter")
game.reduceNum()
game.printNum()
# Or:
print(game())
# As you've changed `__call__` to return the number as well.
I am trying to write a typing challenge game where the player has to type a word as fast as possible within the time limit. At the end of the game() function it is supposed to execute the round1() function when the timer gets to 0. However, nothing happens and it just stays on the number 1. Any ideas what is causing this behavior?
This is the code I am using:
import random
import time
global timer
timer = 20
global counting
counting = 10
global rounds
rounds = 0
def menu():
print ("Main Menu\nType in 'start' to begin the typing challenge")
start = input()
if start == "start":
game()
else:
menu()
def game():
global counting
choices = ["snazzy", "pizzas", "sizzle", "jackal"]
global word
word = (random.choice(choices))
print ("The word you must type is", word)
print ("You will be timed on how long it takes you to type the word.")
print ("Each round you will have a slightly smaller amount of time to type the word")
time.sleep(10)
print ("Starting in...")
for count in range(10):
print (counting)
time.sleep(1)
counting -=1
round1()
def round1():
useless = 100
global rounds
global word
global timer
while useless > 1:
for count in range(20):
time.sleep(1)
timer -=1
print ("Type", word)
attempt = input()
if attempt == word and timer > 0:
rounds = rounds+1
round2()
else:
lose()
You are getting into the function round1, but once you are there, you are caught in an infinite loop because the variable useless will never change.
Even if you take out the while loop, you will never be able to win because you do not take input in until after the timer has already run out.
Try this code from round 1 on:
def round1():
import sys, select
global rounds
global word
global timer
print ("Type", word)
input, out, error = select.select( [sys.stdin], [], [], timer)
if (input):
attempt = sys.stdin.readline().strip()
if attempt == word:
rounds = rounds+1
round2()
else:
lose()
else:
lose()
if __name__ == '__main__':
menu()
Note that, as-is, it will fail with a NameError since you don't have a round2() function defined. A better solution would be to generalize your function, with something like round_x(number, word, time_to_answer); That way you can reuse the same code and don't have to import globals.
I was playing a bit with your game you're doing too many overhead and mistakes
there so I just changed it's structure to simplify:
import random
import time
current_milli_time = lambda:int(time.time() * 1000)
timer = 20 #suppose user has 20 secs to enter a word
counting = 10
requested_word = ""
choices = ["snazzy", "pizzas", "sizzle", "jackal"]
rounds = 0
def menu():
print ("Main Menu\nType in 'start' to begin the typing challenge")
game() if input().lower() == "start" else menu()
#There is no need to split game and round but I didn't want to mess with
#your program structure too much
def game():
global requested_word
try:
requested_word = (random.choice(choices))
choices.remove(requested_word)
except IndexError:
print "Game is finished"
return
print ("The word you must type is", requested_word)
print ("You will be timed on how long it takes you to type the word.")
print ("Each round you will have a slightly smaller amount of time to type the word")
print ("Starting typing in in...")
for count in range(10,-1,-1):
print (count)
time.sleep(1)
round()
def round():
global timer
start = current_milli_time()
word = input("Enter word -> ")
stop = current_milli_time()
time_delta = stop-start #this is in milliseconds
if time_delta< timer*1000 and word == requested_word :
timer = timer-5 #lower the time to enter a word
game()
else:
print("Game OVER")
menu()
When prompt 'Enter word ->' appears the user has all the time he wants to enter a word, but after it time_delta is calculated and if it passes your limit, it's game over for him.
I'm having some issues with this code. There is a lot of other code to go with it but none that will interfere or have any affect on the issue I'm having. So basically, when I run the code and we get to the for loop at the bottom, it prints nothing because apparently the variable 'walls' = 0, even though I've already given it a valid input. If anyone could help it would be much appreciated.
global walls
global wallLengths
walls = 0
wall = 0
wallLengths = 0
def clientDetails():
#global walls
print("Welcome to the InHouse Solutions Room Painting Price Calculator")
print("STEP 1 - CLIENT DETAILS")
print("Please enter your full name")
userName = input(">>>")
print("Please enter your post code")
postCode = input(">>>")
print("Please enter you first address line here:")
addressLineOne = input(">>>")
print("Please enter your second address line here (OPTIONAL)")
addressLineTwo = input(">>>")
print("Thank you for your information")
print (userName)
print (addressLineOne + ", " + addressLineTwo + ", " + postCode)
print (" ")
def ValidationOne():
print ("Is this information correct? Pleast enter Yes or No")
clientDetailsCorrect = input(">>>")
if clientDetailsCorrect == "no" or clientDetailsCorrect == "No":
clientDetails()
elif clientDetailsCorrect == "Yes" or clientDetailsCorrect == "yes":
roomDimensions()
else:
("Invalid response, please try again")
ValidationOne()
ValidationOne()
def roomDimensions():
global walls
print ("STEP 2 - ROOM DIMENSIONS")
def ValidationTwo():
global walls
print ("How many walls does your room have?")
walls = int(input(">>>"))
if walls > 10 or walls < 3:
print("Invalid, please enter a number between 3 and 10")
ValidationTwo()
elif walls == " " or walls == "":
print("Invalid")
ValidationTwo()
def ValidationThree():
global walls
print ("How tall is the room in meters?")
roomHeight = float(input(">>>"))
if roomHeight < 2.4 or roomHeight > 6:
print ("Invalid, please enter a value between 2.4 and 6")
ValidationThree()
def IndividualWalls():
global wallLengths
global walls
for i in range(1,walls):
print("Please enter the width of wall" , i)
wallLengths[i] = float(input(">>>"))
ValidationTwo()
ValidationThree()
IndividualWalls()
clientDetails()
there is no need to use 'global' keyword when declaring a global at the top of the script:
>>> walls = 0
>>> def increase_walls():
... global walls
... walls += 1
... print walls
...
>>> increase_walls()
1
I can't comment to your question because I don't have over 50 reputation so I will ask here
Can you tell me what the function roomDimensions does?
I tried to run it and you have some deep recursion problem (you can't call recursion function without any if - it will run forever) BUT the first thing that I notice is that you don’t initialize the walls variable so it will not be global variable it will be non-local variable. and you don't call any inner function ( ValidationTwo, ValidationThree,IndividualWalls)
so you main problems are: (handle them in this order)
walls initialize
you didn't call any inner function
deep recursion
here is my example for the use of the three of above:
global_var = 12
def outer():
global global_var
print("*"*10)
print('hello im outer function')
print("*"*10)
def inner1():
global global_var
print('hello im inner1 function')
if global_var < 10:
return 'end for inner1'
print ('global_var is: ' + str(global_var))
global_var -= 1
return inner1()
def inner2():
global global_var
print('hello im inner2 function')
if global_var >= 10:
return 'end for inner1'
print ('global_var is: ' + str(global_var))
global_var += 1
return inner2()
if global_var >= 10:
return inner1()
else:
return inner2()
if __name__ == '__main__':
print outer()
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()