Coffee Machine - invalid syntax and End of Statement expected in new function - python

So I'm trying to create a coffee machine program (you choose a drink, the machine checks the ingredients, the resources and the money you insert, then it dispenses the drink.) and it went okay until I got to the part where the program processes the coins and, if sufficient, adds them to the amount of money in the machine.
I'm not really good with return statements and global vs local scopes, so I assume they are the issue. I tried googling, but nothing came up that actually solves the specific problem I have.
This is the code for the function in question:
def process_coins(order, money):
print("Please insert coins.")
quarters = float(input("Quarters: ")) * quarters_value
dimes = float(input("Dimes: ")) * dimes_value
nickles = float(input("Nickles: ")) * nickles_value
pennies = float(input("Pennies: ")) * pennies_value
total = quarters + dimes + nickles + pennies
if total < MENU[order]["cost"]:
total = 0
return print("Sorry, that's not enough money. Money refunded.")
else:
return money += total
PyCharm tells me "End of Statement expected" and "invalid Syntax" for the last line.
When I remove "return" it runs but doesn't actually add the total to the money in the machine. I also tried putting brackets around money += total, which turns both problems into "unexpected expression syntax".
I honestly don't understand why this doesn't work. I just want pycharm to add "total" (local scope) to "money"(global scope) and to return it so I can use it in the rest of the code.
I also don't understand why this function wasn't able to work with the variable "money" before I added it as an argument in the brackets, but it was able to work with the variables "dimes_value" etc. just fine, even though those are mentioned just one line before "money" at the start of the code and aren't part of the arguments in the bracket of the function.
What am I missing?

The problem is that return can only return expressions, but an augmented assignment is a statement. This is why you get a syntax error.
For Python >= 3.8, you can use an assignment expression to overcome this:
return (money := money + total)
* Note the necessary parenthesis.
This will both assign to money and return the value assigned to it.
But this will create a new problem: money will now be considered a local variable (because you assign to it inside the function) and you'll get a different error.
To overcome this, you will need to declare
global money
At the start of the function.
But really the best solution here is not to use global variables at all, simply return money + total, and assign the returned value in the global scope, where you call the function.

if total < MENU[order]["cost"]:
total = 0
return print("Sorry, that's not enough money. Money refunded.")
else:
money += total
return money

Related

How to update a global variable based on number of user inputs?

I am trying to make a list of weights that are being brought to a trip to outer space. The way I have tried to show how many people are coming is this:
def flcr():
try:
Value1 = int(input())
except ValueError:
print("That was an incorrect format! Try again.")
flcr()
global x
x = Value1
Then the user has to input the weights one by one. This is what I tried:
def enter():
print("How much is each flight crew member bringing on the trip? Enter one entry at a time, this will be Earth weight.")
amount1()
def amount1():
try:
if x > 0:
equation1 = [float(input())]
x - 1
amount1()
else:
print(listFlcr)
except ValueError:
print("That was an incorrect format! Try again.")
enter()
When I input the weights though, I assume x just resets itself instead of subtracting itself by 1, so my input is infinite. I want to have a code that will allow me to enter the right amount of weights, so if I say there are 2 people coming, I can only input two weights.
If someone could help me out I would greatly appreciate it!
There are a number of issues with your current implementation.
You are using recursion to repeat getting inputs, which means you have a function (flcr, amount1) that calls itself until valid inputs are provided. While this could work for user inputs, it is usually unnecessary. There are better ways to ask for user input until they give a valid response, and as mentioned in the comments, use a loop instead.
The code x-1 does not update x. It actually does nothing because the result is not stored anywhere. If you are using an IDE or a linter, it could warn you that this is a "pointless statement". What you probably wanted was x = x - 1.
You are using globals to track how many weights need to be input and how many were input so far. While this could also work, it is again unnecessary. It would be simpler to just pass the number of flight crew members as a function argument.
Here's a solution that replaces the recursive calls with while loops and gets the number of people from one function, then passes the result of that to another function for getting the weights:
def get_num_people():
while True:
try:
return int(input("How many people are coming? "))
except ValueError:
print("That was an incorrect format! Try again.")
def get_weights(num_weights):
print("How much is each flight crew member bringing on the trip?")
all_weights = []
while len(all_weights) < num_weights:
try:
all_weights.append(int(input()))
except ValueError:
print("That was an incorrect format! Try again.")
print(all_weights)
return all_weights
num_people = get_num_people()
get_weights(num_people)
Here's the sample output:
$ python test.py
How many people are coming? 2
How much is each flight crew member bringing on the trip?
12
33
[12, 33]
$ python test.py
How many people are coming? 3
How much is each flight crew member bringing on the trip?
abc
That was an incorrect format! Try again.
89
def
That was an incorrect format! Try again.
100
4
[89, 100, 4]
I know that your question was about how to update the global variable based on user inputs, ... but I think you have a global x because you were using recursive calls. A cleaner solution would be to get rid of both recursion and the global variable.
You don't need global before the comparison of x in that function.
Generally for me, I find it easier to refer to things I want global as globals()[‘x’]. That way I know nothing weird will happen. If globals() refers to global namespace, represented similar to a dictionary, globals()[‘x’] will always point to the global variable x.
If it is intended to be global, declare it globally before everything else. Outside all the functions, x = None, or x = 0, or x = ‘’.
try to replace :
Value1 = int(input())
with :
Value1 = int(str(input("")))

How do I create a financial program where I can continuously input amount and show remaining amount in dollars

Trying to create a financial calculation program. I know I have to use loop but how do I loop continuously when the user input float value? I believe I'm wayyyyy off but I am quiet curious how this program can be written for myself so I can utilize this.
I would like something like if I input 10000 then ask for another input for expense... This would give me remaining till I stop input. So it would look something like this
10000 #income
3400 # expense
6600 # remaining
600 #transportation
6000 #remaining
100 #utility expense
5900 #remaining
Do I have the concept right?
def financial_plan ():
c = input ("How much income do you have? ")
income = ()
y = input ("expense?")
expense = ()
z = (income - expense)
for income1 in z:
income1 -= y
print(income1)
This seems like a homework, but still you are a bit on right track so I am answering it for you. Note that you need to convert the input to float, other way around doesn't works.
Few points to clarify your doubts:
If you don't know how many times the loop will run, use while loop.
Use the input function to take input, and apply the float on it to get float value of it.
Put the code inside the function it is supposed to be in if you want it work.
Call the function at the end of the program cause Python is not like C like languages with main function which is called by default.
It is a python code.
def financial_plan ():
income = float(input("How much income do you have? "))
while True:
expense = float(input("Expense: "))
if (income >= expense):
income = income - expense
print("You have remainder balance: " + str(income))
else:
print("Insufficient account balance!!")
continue
if (income == 0):
print("Balance Nil!")
print("Program Ended!")
financial_plan()

How to match input with elements in list/dictionary in Python3

I'm very new at coding, and I'm trying to create a shop list with items and prices on it.
That is, once typed in all the items, the function should calculate the sum and stop the moment you exceed the budget.
So I wrote something like:
def shoplist():
list={"apple":30, "orange":20, "milk":60......}
buy=str(input("What do you want to purchase?")
If buy in list:
While sum<=budget:
sum=sum+??
shoplist ()
I really don't know how to match the input of an item with the price in the list...
My first thought is to use 'if', but it's kinda impractical when you have more than 10 items on the list and random inputs.
I'm in desperate need of help....So any suggestions would be nice!! (or if you have a better solution and think me writing it this way is complete garbage... PLEASE let me know what those better solutions are😭😭😭
The code you post will not run in python. list is a builtin and should not be used for a variable name, and is doubly confusing since it refers to a dict object here. input() already returns a str so the cast has no effect. if and while should be lowercase, and there is no indentation, so we have no way of knowing the limits of those statements.
There are so many things wrong, take a look at this:
def shoplist(budget):
prices = {"apple":30, "orange":20, "milk":60}
# Initialise sum
sum = 0
while sum <= budget:
buy = input("What do you want to purchase?")
# Break out of the loop if the user hts <RETURN>
if not buy: break
if buy in prices:
sum += prices[buy] # This gets the price
else:
print("Invalid item", buy)
shoplist(142)
So what have I changed? The budget has to come from somewhere, so I pass it in as a parameter (142, I made that up). I initialise the sum to zero, and I moved the while loop to the outside.
Notice as well lots of whitespace - it makes the code easier to read and has no effect on performance.
Lots of improvements to make. The user should be shown a list of possible items and prices and also how much budget there is left for each purchase. Note as well that it is possible to go over budget since we might only have 30 in the budget but we can still buy milk (which is 60) - we need another check (if statement) in there!
I'll leave the improvements to you. Have fun!
Take a look at this as an example:
# this is a dictionary not a list
# be careful not using python reserved names as variable names
groceries = {
"apple":30,
"orange":20,
"milk":60
}
expenses = 0
budget = 100
cart = []
# while statements, as well as if statements are in lower letter
while expenses < budget:
# input always returns str, no need to cast
user_input = input("What do you want to purchase?")
if user_input not in groceries.keys():
print(f'{user_input} is not available!')
continue
if groceries[user_input] > budget - expenses:
print('You do not have enough budget to buy this')
user_input = input("Are you done shopping?Type 'y' if you are.")
if user_input == 'y':
break
continue
cart.append(user_input)
# this is how you add a number to anotherone
expenses += groceries[user_input]
print("Shopping cart full. You bought {} items and have {} left in your budget.".format(len(cart), budget-expenses))
I've made some changes to your code to make it work, with explanation including using comments indicated by the # symbol.
The two most important things are that all parentheses need to be closed:
fun((x, y) # broken
fun((x, y)) # not broken
and keywords in Python are all lowercase:
if, while, for, not # will work
If, While, For, Not # won't work
You might be confused by True and False, which probably should be lowercase. They've been that way so long that it's too late to change them now.
budget = 100 # You need to initialize variables before using them.
def shoplist():
prices = { # I re-named the price list from list to prices
'apple' : 30, # because list is a reserved keyword. You should only
'orange' : 20, # use the list keyword to initialize list objects.
'milk' : 60, # This type of object is called a dictionary.
} # The dots .... would have caused an error.
# In most programming languages, you need to close all braces ().
# I've renamed buy to item to make it clearer what that variable represents.
item = input('What do you want to purchase? ')
# Also, you don't need to cast the value of input to str;
# it's already a str.
if item in prices:
# If you need an int, you do have to cast from string to int.
count = int(input('How many? '))
cost = count*prices[item] # Access dictionary items using [].
if cost > budget:
print('You can\'t afford that many!')
else:
# You can put data into strings using the % symbol like so:
print('That\'ll be %i.' % cost) # Here %i indicates an int.
else:
print('We don\'t have %s in stock.' % item) # Here %s means str.
shoplist()
A lot of beginners post broken code on StackOverflow without saying that they're getting errors or what those errors are. It's always helpful to post the error messages. Let me know if you have more questions.

Replacing Iteration with Recursion Python [duplicate]

This question already has answers here:
Is this function recursive even though it doesn't call itself?
(3 answers)
Closed 5 years ago.
I'm just starting to learn about recursion for an EdX course, and I've written an iterative function to calculate the remaining balance after paying the minimum required payment for 12 months.
I was able to easily do it with iteration, but I can't seem to wrap my head around the recursive way.
Please point me in the right direction.
Here is my iterative function
def remaining_balance_iter(balance,annualInterestRate, monthlyPaymentRate ):
'''
This code will take any balance and annual interest rate and calculate the
balance after one year of making the minimum payments
'''
month = 1
monthly_interest_rate = annualInterestRate/12.0
while month <= 12:
minimum_monthly_payment = monthlyPaymentRate * balance
monthly_unpaid_balance = balance - minimum_monthly_payment
balance = monthly_unpaid_balance + monthly_interest_rate*monthly_unpaid_balance
print( "Month {} Remaining balance: ".format(month) + str(round(balance,2)))
month += 1
print ("Remaining balance " + str(round(balance,2)))
I've made an attempt at a recursive function, but it needs work, and I need tutoring haha
def remaining_balance_recur(balance,annualInterestRate, monthlyPaymentRate, month ):
'''
This code will take any balance and annual interest rate and calculate the
balance after one year of making the minimum payments
'''
month = 1
monthly_interest_rate = annualInterestRate/12.0
while month <= 12:
minimum_monthly_payment = monthlyPaymentRate * balance
monthly_unpaid_balance = balance - minimum_monthly_payment
interest = monthly_interest_rate*monthly_unpaid_balance
balance = remaining_balance_recur(monthly_unpaid_balance, annualInterestRate, monthlyPaymentRate, month + 1) + interest
print ("Remaining balance " + str(round(balance,2)))
The best way I've found to deal with recursion is to start by specifying a base case. What is the condition that tells you when you've finished your method? In your code, it looks like you run your method until `month > 12', so your base case would be:
if month > 12:
return 1 # 1 for the purpose of explanation
Your return value for your base case is some base value of your function. What would your script return if your month was 12? That's the value you would return.
Next is the hard part. You have to figure out what variable is being modified by subsequent calls to your method. I'm not exactly sure what your code is intended to do, but it looks like you have a few calculations on some variables. When you use recursion, it's almost as if you're saving the state of the current method call you are executing while you go and retrieve the value you need for your statement. (e.g. a_num = 1 + recurse(n - 1) - you need the value of recurse(n - 1) before you can continue with this statement. This is only an example, though). Look for the variable that is affected by your previous iterations and try to make that recursive. In your situation, it looks like balance is that variable:
balance = balance + remaining_balance_recur(annualInterestRate, monthlyPaymentRate, month + 1)
return balance
When you write a recursive method, you always need to return some value at the end of the method, so the statement that called the method actually gets a value. Here's a short, useless example:
def recurse(n)
if n == 0 # BASE CASE
return 1
some_sum = 0
some_sum += recurse(n - 1) # I need the value from recurse(n - 1)
return some_sum # This method was called somewhere, so it needs to return
Try to figure out a recursive solution for your code from these hints. I'm sorry, recursion is very hard to explain especially over SO. Youtube vids and Google would also be a big help to understand recursion in general. Hope this gave you some ideas.
By putting "month = 1" before the while statement, you are resetting it so that while month <= 12 will run forever. This creates a "RecursionError: maximum recursion depth exceeded in comparison."
The output of your function is currently "NoneType" because its output is a print statement rather than returning an int or a float. This produces a "TypeError" because you have tried to add a float (the interest rate) to a NoneType (the printed statement) in your recursion.

Answer Error, Only outputting Zero

I am coding in python and I cannot seem to figure out why when the amount of tickets sold is entered it does not calculate the full price of the tickets that were sold. Any help is appreciated, Thanks.
aLimit=300
bLimit=500
cLimit=100
aPrice=20
bPrice=15
cPrice=10
ticketSold=1
totalIncome=0
def Main():
getTickets(aLimit)
sectionIncome=calcIncome(ticketSold,aPrice)
sectionIncome+=totalIncome
print("The theater generated this much money from section A "+
str(sectionIncome))
getTickets(bLimit)
sectionIncome=calcIncome(ticketSold,bPrice)
sectionIncome+=totalIncome
print("The theater generated this much money from section B "+
str(sectionIncome))
getTickets(cLimit)
sectionIncome=calcIncome(ticketSold,cPrice)
sectionIncome+=totalIncome
print("The theater generated this much money from section C "+
str(sectionIncome))
print("The Theater generated "+str(totalIncome)+" total in ticket sales.")
def getTickets(limit):
ticketSold=int(input("How many tickets were sold? "))
if (ticketsValid(ticketSold,limit)==True):
return ticketSold
else:
getTickets(limit)
def ticketsValid(Sold,limit):
while (Sold>limit or Sold<0):
print("ERROR: There must be tickets less than "+
str(limit)+" and more than 0")
return False
return True
def calcIncome(ticketSold,price):
return ticketSold*price
Main()
How to debug your (small) program
Okay so let's start from the top and go line-by-line. There's a lot of issues here.
aLimit=300
bLimit=500
cLimit=100
aPrice=20
bPrice=15
cPrice=10
ticketSold=1
totalIncome=0
These are all globals since you defined them in the module scope. That's a Bad Thing. Don't do it. If they're constants, use CAPS to mention that, but they should still not be global.
def Main(): # I mentioned in my comment, but Capitals are classes
# by convention, use def main() instead
getTickets(aLimit)
Let's stop and look at getTickets() so we can follow execution
def getTickets(limit): # camelCase is not advised per PEP8, but it's still around
# so I wouldn't worry about this one so much as Capitalized
ticketSold=int(input("How many tickets were sold? "))
# perfect implementation, though be prepared for users who
# will type forty instead of 40!
if (ticketsValid(ticketSold,limit)==True):
return ticketSold
# so any time you write `if ___ == True`, stop and realize that the compare
# is unnecessary. if ticketsValid(ticketSold,limit) works just as well!
else:
getTickets(limit)
# wha-? If the tickets aren't valid, we're RECURSING??! This is an infinite loop.
# are you doing this to prompt for more input if tickets aren't valid? That's Bad
Okay so you invoked ticketsValid in there, so let's look there now...
def ticketsValid(Sold,limit): # another Capital here!
while Sold > limit or Sold < 0: # this should be an if??
print ("...")
return False
return True
# Since you have a set amount, this is MUCH easier written as:
## def ticketsValid(sold,limit):
## return 0 < sold < limit
# but should this be <=?
Alright, back to main--ahem--Main....
def Main():
...
sectionIncome = calcIncome(ticketSold,aPrice)
And hop back to calcIncome
def calcIncome(ticketSold,price):
return ticketSold*price # why not just substitute this???
Main again
def Main():
...
sectionIncome += totalIncome
# this sets sectionIncome equal to the current value of sectionIncome
# plus the current value of totalIncome, which is currently zero.
Then basically the whole thing gets repeated down the function. There's your issue, the += adds zero to sectionIncome instead of adding sectionIncome to totalIncome!
The better way to do this!
Here's the problem. You're trying to use functional programming to do object-oriented tasks. Most of these kind of issues are when new programmers who are interested in video games think that the best task to learn programming is a text adventure. Unfortunately, the best languages for text adventures (those that easily implement a Finite State Machine) are not usually those that beginners start with, so it's hard to implement WELL!
In your case, you should be creating objects to do the workload for you. Python does this elegantly, but it's rarely in beginning tutorials. As an example, I wrote out a bit that does exactly what you did (defines three sections of seating in a theater and sells one ticket per section)
class Section(object):
def __init__(self,price,limit):
self.price = price
self.tickets_sold = 0
self.limit = limit
#property
def sales(self):
return self.price*self.tickets_sold
def sell(self,qty=1):
if not isinstance(qty,int): raise TypeError("Must sell an int of tickets")
if qty < 1: raise ValueError("Must sell positive tickets")
qty = min(qty,self.limit-self.tickets_sold)
self.tickets_sold += qty
# optional print statement for the user
class Theater(object):
def __init__(self,sections):
self.sections = sections
#property
def sales(self):
return sum(section.sales for section in self.sections)
theater = Theater([Section(20,300),
Section(15,500),
Section(10,100)])
for section in theater.sections:
section.sell(1)
print(theater.sales)
The big problem with this is just that you don't know how to do it. Creating an object that will stay constant, then throw several instances of it around with specific attributes is precisely the approach I would favor in this circumstance.
read up on the += operator. totalIncome is only ever set to 0.
You need to replace sectionIncome+=totalIncome with totalIncome+=sectionIncome
Code
aLimit=300
bLimit=500
cLimit=100
aPrice=20
bPrice=15
cPrice=10
ticketSold=1
totalIncome=0
def Main():
getTickets(aLimit)
sectionIncome=calcIncome(ticketSold,aPrice)
totalIncome=sectionIncome
print("The theater generated this much money from section A "+str(sectionIncome))
getTickets(bLimit)
sectionIncome=calcIncome(ticketSold,bPrice)
totalIncome+=sectionIncome
print("The theater generated this much money from section B "+str(sectionIncome))
getTickets(cLimit)
sectionIncome=calcIncome(ticketSold,cPrice)
totalIncome+=sectionIncome
print("The theater generated this much money from section C "+str(sectionIncome))
print("The Theater generated "+str(totalIncome)+" total in ticket sales.")
def getTickets(limit):
ticketSold=int(input("How many tickets were sold? "))
if (ticketsValid(ticketSold,limit)==True):
return ticketSold
else:
getTickets(limit)
def ticketsValid(Sold,limit):
while (Sold>limit or Sold<0):
print ("ERROR: There must be tickets less than "+str(limit)+" and more than 0")
return False
return True
def calcIncome(ticketSold,price):
return ticketSold*price
Main()
sectionIncome+=totalIncome
This is the wrong way around. To add to totalIncome the value of sectionIncome, the syntax is
totalIncome+=sectionIncome
You will allso need to add global totalIncome to the beginning of Main -- or, better yet, do away with the global variables completely, like you have often been told before.
Finally, your getTickets function returns a calculated value, but the code which calls it doesn't store that result anywhere. Instead, you simply set ticketSold=1 in the global initialization, then use that as the multiplier instead of the actual number of tickets input by the user.
As a general observation, you have a lot of repetitive code, while the functions you do have are not very useful (they do not encapsulate complex behavior, nor repeated functionality). If you are a beginner, concentrate on a straightforward flow, then factor out complex repeating operations to loops or functions. Perhaps something like this:
def income ():
total = 0
for ticket_type, limit, price in [('A', 300, 20),
('B', 500, 15),
('C', 100, 10)]:
print "How many %s tickets sold? (Max %d):" % (ticket_type, limit),
sold = -1
while sold < 0 or sold > limit:
if sold != -1:
print "Sorry. Try again:",
sold = raw_input()
try:
sold = int(sold)
except:
pass
total += sold*price
print "total %d" % total
income()
Please also note the user-friendly gesture of indicating the maximum allowed for each category in the input prompt (-:
The loop driver is a bit of a wart; a slicker way to do that would be to declare a class TicketCategory and have three instances A, B, and C with methods to report back their name, price, and available amounts, but that's for later.

Categories

Resources