Python local variable referenced before as assignment - python

So basically i defined the variable before (globally)
However, it still says variable referenced before assignment.
I am a beginner and i dont know how to use this so please forgive me if i am doing something wrong
import time
import multiprocessing
i = True
upgrade_level = 0
money = 10
def clear_chat():
num = 0
while num < 100:
print(" ")
num += 1
def loop1():
while i:
question = input("Would you like to upgrade? (y)\n")
if(question.lower() == "y"):
if(money >= 10):
clear_chat()
money = money-10
print("You upgraded once")
print("Your upgrade level is " + str(upgrade_level))
elif(money < 10):
clear_chat()
print("You do not have enough money ($10) to buy an upgrade")
else:
clear_chat()
print("You can only input (y)")
def loop2():
while i:
money += 10
time.wait(10)
p1 = multiprocessing.Process(target = loop1())
p2 = multiprocessing.Process(target = loop2())

import time
import multiprocessing
i = True
upgrade_level = 0
money = 10
def clear_chat():
num = 0
while num < 100:
print(" ")
num += 1
def loop1():
global money
while i:
question = input("Would you like to upgrade? (y)\n")
if(question.lower() == "y"):
if(money >= 10):
clear_chat()
money = money-10
print("You upgraded once")
print("Your upgrade level is " + str(upgrade_level))
elif(money < 10):
clear_chat()
print("You do not have enough money ($10) to buy an upgrade")
else:
clear_chat()
print("You can only input (y)")
def loop2():
global money
while i:
money += 10
time.wait(10)
p1 = multiprocessing.Process(target = loop1())
p2 = multiprocessing.Process(target = loop2())
I included global keyword below loop1 func declaration

First time.wait() is accully time.sleep().
The main problem in your code is, you haven't added the global keyword in function. you can read the global variable without global keyword, but in order to make changes in it you have to use global keyword, i.e use global money in both loops.
Instead of clear_chat() functions, you can use the following:
if os.name == 'posix':
os.system('clear') # for MAC os and linux
else:
os.system('cls') # for windows platform
To clear the python screen or Console.

You need to add the global keyword in each function where you want to use it to access it like this,
import time
import multiprocessing
i = True
upgrade_level = 0
money = 10
def clear_chat():
num = 0
while num < 100:
print(" ")
num += 1
def loop1():
global money
while i:
question = input("Would you like to upgrade? (y)\n")
if(question.lower() == "y"):
if(money >= 10):
clear_chat()
money = money-10
print("You upgraded once")
print("Your upgrade level is " + str(upgrade_level))
elif(money < 10):
clear_chat()
print("You do not have enough money ($10) to buy an upgrade")
else:
clear_chat()
print("You can only input (y)")
def loop2():
global money
while i:
money += 10
time.wait(10)
p1 = multiprocessing.Process(target = loop1())
p2 = multiprocessing.Process(target = loop2())
Can read this for examples https://www.w3schools.com/python/python_variables_global.asp

You need to specify that the variable 'money' in both functions is the global one you initialized beforehand using the keyword global. Like this:
import time
import multiprocessing
i = True
upgrade_level = 0
money = 10
def clear_chat():
num = 0
while num < 100:
print(" ")
num += 1
def loop1():
global money
while i:
question = input("Would you like to upgrade? (y)\n")
if(question.lower() == "y"):
if(money >= 10):
clear_chat()
money = money-10
print("You upgraded once")
print("Your upgrade level is " + str(upgrade_level))
elif(money < 10):
clear_chat()
print("You do not have enough money ($10) to buy an upgrade")
else:
clear_chat()
print("You can only input (y)")
def loop2():
global money
while i:
money += 10
time.wait(10)
p1 = multiprocessing.Process(target = loop1())
p2 = multiprocessing.Process(target = loop2())
However, note that the i variable is never changed to False and that creates an infinite loop.
Check this article for more info on the error: Article

Related

How do I apply the sellProduct method to each choice in the menu?

I don't understand why I can't connect the processSale method to the sellProduct method. I think that the classes and other methods don't need any change because I only followed the criterias that were given to me.
#candy machine
class CashRegister:
def __init__(self, cashOnHand = 500,):
if cashOnHand < 0:
self.cashOnHand = 500
else:
self.cashOnHand = cashOnHand
def currentBalance(self):
return self.cashOnHand
def acceptAmount(self, cashIn):
self.cashOnHand += cashIn
class Dispenser:
def __init__(self, numberOfItems = 50, productCost = 50):
if numberOfItems < 0:
self.numberOfItems = 50
else:
self.numberOfItems = numberOfItems
if productCost < 0:
self.productCost = 50
else:
self.productCost = productCost
def getCount(self):
return self.numberOfItems
def getProductCost(self):
return self.productCost
def makeSale(self):
self.numberOfItems -= 1
class MainProgram:
def showMenu(self):
global userInput
print("**** Welcome to Eros' Candy Shop ****")
print("To select an item enter")
print("""1 for Candy
2 for Chips
3 for Gum
4 for Cookies
0 to View Balance
9 to Exit""")
userInput = int(input("Enter your choice: "))
def sellProduct(self, useDispenser = Dispenser(), useRegister = CashRegister()):
try:
self.useDispenser = useDispenser
self.useRegister = useRegister
if self.useDispenser.getCount != 0:
print(f"It costs {self.useDispenser.getProductCost} cents")
cash = int(input("Please enter your payment: "))
change = cash - self.useDispenser.getProductCost
if change < 0:
print("Insufficient money!")
print(f"You need {self.useDispenser.getProductCost - cash} cents more")
return
else:
print(f"Your change is {change} cents")
self.useRegister.acceptAmount(self.useDispenser.getProductCost)
self.useDispenser.makeSale
return
elif self.useDispenser.getCount == 0:
print("The product you chose is sold out! Try the other itmes")
return
except ValueError:
print("You entered an incorrect value. Please use the numbers on the menu only")
def processSale(self):
Register = CashRegister()
Candy = Dispenser()
Chips = Dispenser()
Gum = Dispenser()
Cookies = Dispenser()
while True:
self.showMenu
if userInput == 1:
self.sellProduct(Candy, Register)
elif userInput == 2:
self.sellProduct(Chips, Register)
elif userInput == 3:
self.sellProduct(Gum, Register)
elif userInput == 4:
self.sellProduct(Cookies, Register)
elif userInput == 0:
print("Current Balance is" + str(Register.currentBalance))
elif userInput == 9:
break
mainProgram = MainProgram()
mainProgram.showMenu()
How do i use sellProduct method on userInput 1-4. I get confused when applying the properties of a class and how to connect them. Can you point out what mistakes I made and what other improvements I can do.
here are some points you can improve :
When you call your methods do not forget the parenthesis :
self.useDispenser.getCount()
self.useDispenser.getProductCost()
Create an infinite loop to continuously ask for input within showMenu and delete the one within processSale (for example):
def showMenu(self):
global userInput
userInput = 0
print("**** Welcome to Eros' Candy Shop ****")
while userInput != 9:
print("To select an item enter")
print(MENU)
userInput = int(input("Enter your choice: "))
if userInput < 9:
self.processSale()
But please update the whole program accordingly.
Hope it helps !

Python 3: Returning variable through multiple functions

I have been given a basic python problem that requires me to make a simple addition quiz. However, I cannot seem to return my count variable which is supposed to update the number of correct questions the user has answered, which makes it stuck at 0. I have tried defining the variable count in every function containing it as an argument but still does not work. Say if the user were to answer 4 questions and got 3 correct, it would display it as "You have answered 4 questions with 3 correct", but instead it displays "You have answered 4 questions with 0 correct".
Every time your check_solution and menu_optionfunctions get called, you initialize count = 0. This means every time the user requests another question, count gets reset to 0, twice. You're going to want to remove those count = 0 calls, and you also want to capture your updates to count within menu_option. Your final program should look something like this:
import random
def get_user_input():
count = 0
user_input = int(input("Enter 1 to play or press 5 to exit: "))
while user_input > 5 or user_input <= 0:
user_input = int(input("Invalid menu option. Try again: "))
menu_option(user_input, count)
if user_input == "5":
print("Exit!")
return user_input
def get_user_solution(problem):
answer = int(input(problem))
return answer
def check_solution(user_solution, solution, count):
curr_count = count
if user_solution == solution:
curr_count += 1
print("Correct.")
else:
print("Incorrect.")
print(curr_count)
return curr_count
def menu_option(index, count):
if index == 1:
num1 = random.randrange(1, 21)
num2 = random.randrange(1, 21)
randsum = num1 + num2
problem = str(num1) + " " + "+" + " " + str(num2) + " " + "=" + " "
user_answer = get_user_solution(problem)
count = check_solution(user_answer, randsum, count) # count returned by check_solution is now being captured by count, which will update your count variable to the correct value
return count
def display_result(total, correct):
if total == 0:
print("You answered 0 questions with 0 correct.")
print("Your score is 0%. Thank you.")
else:
score = round((correct / total) * 100, 2)
print("You answered", total, "questions with", correct, "correct.")
print("Your score is", str(score) + "%.")
def main():
option = get_user_input()
total = 0
correct = 0
while option != 5:
total = total + 1
correct = menu_option(option, correct)
option = get_user_input()
print("Exiting.")
display_result(total, correct)
main()
You need catch the return from check_solution(user_answer, randsum, count) and return that count
As the comment stated, you are initializing count to 0 every time your check_solution or menu_option is called.
It looks like you want to use count = count the variable being passed to your function.
Just a quick edit:
You actually don't need to return count. In Python, variables are passed by reference so your count will get updated as long as it's being passed to your functions.
You have the option of initializing count to 0 before all functions, thus creating a global variable. Then you won't need to declare it on any function nor pass it as argument.
This is a culmination of several errors in logic.
You give count to functions as input and immediately overwrite it.
I would instead say def menu_option(index, count=0):. This will set count=0 if no variable is supplied (creating a default), otherwise it will set count as whatever you pass into the function
Your check_solution() function returns a number, but when you call it with check_solution(user_answer, randsum, count) you never assign this returned value to anything/use it again.
You can assign this to a variable (say output) and then return output instead of return count
Fixing these still doesn't fully solve the problem, but gets a little bit closer (now it gets stuck on "you answered x questions with 1 correct"):
import random
def get_user_input(count = 0):
user_input = int(input("Enter 1 to play or press 5 to exit: "))
while user_input > 5 or user_input <= 0:
user_input = int(input("Invalid menu option. Try again: "))
menu_option(user_input, count)
if user_input == "5":
print("Exit!")
return user_input
def get_user_solution(problem):
answer = int(input(problem))
return answer
def check_solution(user_solution, solution, count):
count = 0
if user_solution == solution:
count += 1
print("Correct.")
else:
print("Incorrect.")
return count
def menu_option(index, count=0):
if index == 1:
num1 = random.randrange(1, 21)
num2 = random.randrange(1, 21)
randsum = num1 + num2
problem = str(num1) + " " + "+" + " " + str(num2) + " " + "=" + " "
user_answer = get_user_solution(problem)
output = check_solution(user_answer, randsum, count)
return output
def display_result(total, correct):
if total == 0:
print("You answered 0 questions with 0 correct.")
print("Your score is 0%. Thank you.")
else:
score = round((correct / total) * 100, 2)
print("You answered", total, "questions with", correct, "correct.")
print("Your score is", str(score) + "%.")
def main():
option = get_user_input()
total = 0
correct = 0
while option != 5:
total += 1
correct = menu_option(option, correct)
option = get_user_input()
print("Exiting.")
display_result(total, correct)
main()
I think a more simplistic approach would look something like:
import random
def generate_question():
num1 = random.randint(1, 25)
num2 = random.randint(1, 25)
question = '{} + {} = '.format(num1, num2)
answer = num1 + num2
return question, answer
def main():
correct = 0
total = 0
option = True
while option != '5':
total += 1
question, answer = generate_question()
user_guess = int(input(question))
if user_guess == answer:
print('Correct.')
correct += 1
else:
print('Incorrect.')
option = input("Enter 5 to exit, or anything else to play again")
print('You answered {} questions with {} correct'.format(total, correct))
main()

Function unable to change variable

I am trying to make a full-on guessing game with a shop that you can buy stuff with coins. but I had a function that was supposed to give the user a certain amount of coins depending on how many attempts it took them to guess the number. However, when I have a variable called 'coins' and when a player gets the number, I add coins to 'coins' it doesn't actually add coins. When I print 'coins' it still tells me 0. It's very confusing I know but I just want to fix this. I am using a mac with python 3, and am using two files, one for the main code, and the other for the functions. Do you see where I'm going wrong?
Main Code:
from guessing_functions import guess_game, guess_home
home = False
attempt = 0
coins = 0
print ("Atemps:Coins, 10:5, 7:10, 5:20, 3:40, 1:100 ")
guess_game(coins, attempt)
while not home:
guess_home(coins)
Functions:
import random
def guess_game(coins, attempt):
print ("This is a guessing game. ")
found = False
num = random.randint(1, 100)
while not found:
userGuess = input('Your Guess: ') ; userGuess = int(userGuess)
if userGuess == num:
print ("You got it!")
found = True
elif userGuess > num:
print ("Guess Lower!")
else:
print ("Guess Higher")
attempt += 1
if attempt == 1 and found == True:
print ("You won 100 coins!")
coins += 100
elif attempt == 2 and found == True:
print ("You won 40 coins")
coins += 40
elif attempt == 3 and found == True:
print ("You won 40 coins")
elif attempt == 4 and found == True:
print ("You won 20 coins")
coins += 20
elif attempt == 5 and found == True:
print ("You won 20 coins")
coins += 20
elif attempt == 6 and found == True:
print ("You won 10 coins")
coins += 10
elif attempt == 7 and found == True:
print ("You won 10 coins")
coins += 10
elif attempt == 8 and found == True:
print ("You won 5 coins")
coins += 5
elif attempt == 9 and found == True:
print ("You won 5 coins")
coins += 5
elif attempt == 10 and found == True:
print ("You won 5 coins")
coins += 5
Your function uses coins in it's local scope. In order for the function to change the value of the outter scope (global) coins variable you need to explicity state that.
Add global coins inside your function before changing coins value.
coins = 0
def f():
global coins
coins = 5
f()
print coins
# 5
Or, an alternative way is to return coins value from the function, and call your function coins = guess_game(attempt)
Here is some useful resource for this subject
To get it to work, you need only add return coins to the end of the guess_game function and collect the returned value in your main code as coins = guess_game(coins, attempt). However, if you'd like, you can simplify your code a little bit like so:
import random
def guessing_game(coins):
print("This is a guessing game. ")
attempts = 0
number = random.randint(1, 100)
user_guess = -number
while user_guess != number:
user_guess = int(input("Your Guess: "))
if user_guess > number:
print("Guess Lower!")
elif user_guess < number:
print("Guess Higher")
else:
print("You got it!")
if attempts == 1:
winnings = 100
elif attempts in [2, 3]:
winnings = 40
elif attempts in [4, 5]:
winnings = 20
elif attempts in [6, 7]:
winnings = 10
elif attempts in [8, 9, 10]:
winnings = 5
else:
winnings = 0
print("You won {} coins!".format(winnings))
return coins + winnings
attempts += 1
With your main code as:
from guessing_functions import guessing_game
coins = 0
print("Starting balance: {} coins".format(coins))
print ("Winnings vs. Attempts: 10:5, 7:10, 5:20, 3:40, 1:100")
coins = guessing_game(coins)
print("Current balance: {} coins".format(coins))
Where the output from a sample run is as follows:
Starting balance: 0 coins
Winnings vs. Attempts: 10:5, 7:10, 5:20, 3:40, 1:100
This is a guessing game.
Your Guess: 50
Guess Lower!
Your Guess: 25
Guess Higher
Your Guess: 37
Guess Higher
Your Guess: 44
Guess Higher
Your Guess: 47
Guess Lower!
Your Guess: 46
You got it!
You won 20 coins!
Current balance: 20 coins
You should return the number of coins from the function and assign it to coins:
def guess_game(coins, attempt):
... # code to determine coin amount
return coins
coins = guess_game(coins, attempt)
Defining Functions

Accessing returned values from a function, by another function

I'm kinda new to programming in general, just started to really get into python.
And I'm working on a number guesser project.
import random
def main(): # main function
print("Welcome to the number guesser game")
range_func()
max_guess_number(lower_range_cut, upper_range_cut)
evaluation(random_number, total_guesses)
def range_func(): # allows user to select a range for the number guess
print("Please select a range in which you would like to guess.")
lower_range_cut = int(input("Lower boundary limit: "))
global lower_range_cut
upper_range_cut = int(input("Upper boundary limit: "))
global upper_range_cut
random_number = random.randint(lower_range_cut,upper_range_cut)
global random_number
return lower_range_cut, upper_range_cut, random_number
def max_guess_number(low,high): # returns the total number of guesses
total_numbers = (high - low) + 1
total_guesses = 0
while (2**total_guesses) < total_numbers:
total_guesses += 1
print ("You have a total of %d guesses\n"
"for your range between %d to %d"
% (total_guesses, low, high))
global total_guesses
return total_guesses
def evaluation(random_number, total_guesses): # evaluates the users input
guess_count = 0
while guess_count < total_guesses:
user_guess = int(input("Your guess: "))
print("Your guess is: %d" % (user_guess))
if (random_number == user_guess):
print("You got it ")
break
elif user_guess > random_number:
print("Guess lower!")
guess_count += 1
else:
print("Guess higher!")
guess_count += 1
if __name__ == "__main__":
main()
One problem I've experienced while writing that, is that I wasn't able to execute this program without redefining each variables as a global variable. Just by returning the values from one function, I was not able to access e.g. the second returned variable upper_range_cut from the range_function
It there a way to handle that somehow shorter?
Also I'm happy about every note on the code itself (readability, function use, length). I know it could have made this code a lot shorter maybe by using list comprehension, but I don't really have the eye for seeing opportunities in this area yet.
So thanks for any help!
KiliBio
You're pretty much there. You can remove all globals, then just store the values returned from each function to local variables, and pass them in to new functions.
The only other changes I've made below are:
Breaking out of the evaluation loop if the answer is guessed correctly.
Printing a message if no guess is found in the given time. See: Else clause on Python while statement
The bottom two lines allow the script to be run from the command line. See: What does if __name__ == "__main__": do?
Otherwise you're looking good.
import random
def main(): # main function
print("Welcome to the number guesser game")
lower, upper, rand = range_func()
total_guesses = max_guess_number(lower, upper)
evaluation(rand, total_guesses)
def range_func(): # allows user to select a range for the number guess
print("Please select a range in which you would like to guess.")
lower_range_cut = int(input("Lower boundary limit: "))
upper_range_cut = int(input("Upper boundary limit: "))
random_number = random.randint(lower_range_cut, upper_range_cut)
return lower_range_cut, upper_range_cut, random_number
def max_guess_number(low,high): # returns the total number of guesses
total_numbers = (high - low) + 1
total_guesses = 0
while (2**total_guesses) < total_numbers:
total_guesses += 1
print ("You have a total of %d guesses\n"
"for your range between %d to %d"
% (total_guesses, low, high))
return total_guesses
def evaluation(random_number, total_guesses): # evaluates the users input
guess_count = 0
while guess_count < total_guesses:
guess_count += 1
user_guess = int(input("Your guess: "))
print("Your guess is: %d" % (user_guess))
if (random_number == user_guess):
print("You got it!")
break
else:
print "Sorry, you didn't guess it in time. The answer was: %d" % random_number
if __name__ == '__main__':
main()
You don't need to define global. You can just assign the values you are returning from a function to variable(s).
A simple example:
def add(a, b):
"""This function returns the sum of two numbers"""
return a + b
Now in your console, you could do following
# print the return
>>> print(add(2, 3))
5
# assign it to a variable
>>> c = add(2, 3)
>>> c
5
In your main function you need to assign the values which are returned by different functions to variables which you can further pass to other functions.
def main(): # main function
print("Welcome to the number guesser game")
lower_range_cut, upper_range_cut, random_number = range_func()
total_guesses = max_guess_number(lower_range_cut, upper_range_cut)
evaluation(random_number, total_guesses)

My game wont go to my function

Well here's the problem my game() function wont go to my firstlevel() function and just keeps says process exited with exit code 0 And I have no clue why I even tried changing the function name And still no luck I truly have no clue what to do I am just a beginner...
code:
import winsound
import random as ran
import pickle
profile = {}
def fightsound():
winsound.PlaySound('fight2.wav', winsound.SND_FILENAME | winsound.SND_ASYNC)
def ranking():
if profile['xp'] >= 20:
profile['level'] += 1
if profile['xp'] >= 50:
profile['level'] += 1
if profile['xp'] >= 100:
profile['level'] += 1
game()
else:
game()
else:
game()
else:
game()
def play_bgmusic():
winsound.PlaySound('mk.wav', winsound.SND_FILENAME | winsound.SND_ASYNC)
def load_game():
global profile
profile = pickle.load(open("save.txt", "rb"))
game()
def fatality():
winsound.PlaySound('fatal2.wav', winsound.SND_FILENAME | winsound.SND_ASYNC)
def game():
global profile
print("Player: " + profile['player'])
print("XP: ", profile['xp'])
print("Level: ", profile['level'])
print("win: ", profile['win'])
print("loss: ", profile['loss'])
if profile['level'] >= 1:
print("1.) The ogre king...")
if profile['level'] >= 2:
print("2.) The realm of the witch!")
y = input("Select an option -> ")
if y == 1:
firstlevel()
def firstlevel():
global profile
fightsound()
enemyhp = 50
hp = 100
while enemyhp > 0:
print("Your hp: ", hp, " Enemy hp: ", enemyhp)
input("Press enter to attack...")
damage = ran.randint(0, 25)
enemyhp -= damage
damage = ran.randint(0, 25)
hp -= damage
if hp <= 0:
profile['xp'] += 5
profile['loss'] += 1
pickle.dump(profile, open("save.txt", "wb"))
print("You died, press enter to continue...")
game()
fatality()
profile['xp'] += 10
profile['win'] += 1
pickle.dump(profile, open("save.txt", "wb"))
input("You win! Press enter to continue...")
ranking()
def new_game():
global profile
player = input("Enter a player name -> ")
profile['player'] = player
profile['xp'] = 0
profile['level'] = 1
profile['win'] = 0
profile['loss'] = 0
pickle.dump(profile, open("save.txt", "wb"))
game()
def main():
play_bgmusic()
print(20 * "-")
print("| |")
print("| 1.) New Game |")
print("| 2.) Load Game |")
print("| 3.) Credits |")
print("| |")
print(20 * "-")
x = int(input("Select an option -> "))
if x == 1:
new_game()
if x == 2:
load_game()
if x == 3:
pass
main()
The problem is these three lines:
y = input("Select an option -> ")
if y == 1:
firstlevel()
When you get input, it will come back as a string. You are comparing the string "1" to the integer 1. The two are not equal, so firstlevel() is never called.
You should convert the string to an integer, or change the integer to a string, so that you are comparing two objects of the same type.
Gonna bet it's cause y isn't what you think it is. Try printing it out or putting a breakpoint on it to make sure it is an integer with value 1.
The problem is here:
y = input("Select an option -> ")
if y == 1:
input() returns a string, so it will never be equal to the integer 1. Simply use int() on y before your comparison and you'll be good to go.

Categories

Resources