How do I limit individual dictionary inputs in Python? - python

Is there a way to put limitations on the integer input of a dictionary? The current way I have it set up checks the whole dictionaries individual inputs after, is there a way I can set it up so it can give more instant feed back. E.g. User inputs an integer value of 6 then an error and prompt appears straight away?
def shop_dictionary(shop):
shop_dict = {}
for key in range(1, shop + 1):
shop_name = f"Shop {key}"
while True:
try:
shop_dict[shop_name] = {
"Chocolate": int(input(f"{shop_name} Chocolate Amount: ")),
"Strawberry": int(input(f"{shop_name} Strawberry Amount: ")),
"Vanilla": int(input(f"{shop_name} Vanilla Amount: ")),
}
break
except ValueError:
print(
"Invalid. Please enter an amount between 1 and 5."
)
if shop_dict[shop_name]["Chocolate"] < 1 or shop_dict[shop_name]["Chocolate"] > 5:
print("Invalid number. Please enter a number between 1 and 5.")
shop_dict[shop_name]["Chocolate"] = int(input(""))
if shop_dict[shop_name]["Strawberry"] < 1 or shop_dict[shop_name]["Strawberry"] > 5:
print("Invalid number. Please enter a number between 1 and 5.")
shop_dict[shop_name]["Strawberry"] = int(input(""))
if (
shop_dict[shop_name]["Vanilla"] < 1
or shop_dict[shop_name]["Vanilla"] > 5
):
print("Invalid number. Please enter a number between 1 and 5.")
shop_dict[shop_name]["Vanilla"] = int(input(""))
return shop_dict
Preferably I would like to know if this is possible during the input stage, is there something I could write that would do something like the following?
shop_dict[shop_name] = {
"Chocolate": integer between range of 1 to 5(input(f"{shop_name} Chocolate Amount: ")),
"Strawberry": integer between range of 1 to 5(input(f"{shop_name} Strawberry Amount: ")),
"Vanilla": integer between range of 1 to 5(input(f"{shop_name} Vanilla Amount: ")),
}
Thanks. Sorry for the noob question.

Create a helper function that doesn't return until user enters correct value.
def get_int(prompt, minn, maxx):
while True:
try:
val = int(input(prompt))
if minn <= val <= maxx:
return val
except:
pass
print(f"Invalid number. Please enter a number between {minn} and {maxx}.")
def shop_dictionary(shop):
flavors = ["Chocolate", "Strawberry", "Vanilla"]
shop_dict = {}
for key in range(1, shop + 1):
shop_name = f"Shop {key}"
shop_dict[shop_name] = {flavor: get_int(f"{shop_name} {flavor} Amount: ", 1, 5) for flavor in flavors}
return shop_dict
If you are not familiar with dictionary comprehension, the line
shop_dict[shop_name] = {flavor: get_int(f"{shop_name} {flavor} Amount: ", 1, 5) for flavor in flavors}
is the same as
shop_dict[shop_name] = {}
for flavor in flavors:
shop_dict[shop_name][flavor] = get_int(f"{shop_name} {flavor} Amount: ", 1, 5)

Related

UnboundLocalError: local variable var referenced before assignment - how to debug [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 months ago.
Improve this question
I'm working through a tutorial based on this and have hit this error.
I am trying to work up my skill in Python and am not sure how to debug this because the error confuses me.
import random
MAX_LINES = 3
MAX_BET = 100
MIN_BET = 1
ROWS = 3
COLS = 3
symbol_count = {
"A": 2,
"B": 4,
"C": 6,
"D":8
}
symbol_value = {
"A": 5,
"B": 4,
"C": 3,
"D":2
}
def check_winnings(columns, lines, bet, values):
winnings - 0
winning_lines = []
for line in range(lines):
symbol = columns[0][line]
for column in columns:
symbol_to_check = column[line]
if symbol != symbol_to_check:
break
else:
winnings += values[symbol] * bet
winning_lines.append(lines +1) # Add one because index starts at 0 and it needs to start at 1
return winnings, winning_lines
def get_slot_machine_spin(rows, cols, symbols):
all_symbols = []
for symbol, symbol_count in symbols.items():
for _ in range(symbol_count): #The _ is an anonymous value
all_symbols.append(symbol)
#print(all_symbols)
columns = []
for _ in range(cols):
column = []
current_symbols = all_symbols[:]# This creates a copy of all symbols
for _ in range(rows):
value = random.choice(current_symbols)
current_symbols.remove(value)
column.append(value)
columns.append(column)
return columns
def print_slot_machine(columns):
for row in range(len(columns[0])):
for i,column in enumerate(columns):
if i != len(columns) - 1:
print(column[row], end = " | ")
else:
print(column[row], end="")
print()
def deposit():
while True:
amount = input("What would you like to deposit?")
if amount.isdigit():
amount = int(amount)
if amount > 0:
break
else:
print("Amount must be greater than zero.")
else:
print("Please enter a number.")
return amount
def get_number_of_lines():
while True:
lines = input("Enter the number of lines to bet on (1-" + str(MAX_LINES) + "? ")
if lines.isdigit():
lines = int(lines)
if 1 <= lines <= MAX_LINES:
break
else:
print("Enter a valid number of lines.")
else:
print("Please enter a number.")
return lines
def get_bet():
while True:
amount = input("How much would you like to bet on each line?")
if amount.isdigit():
amount = int(amount)
if MIN_BET <= amount <= MAX_BET:
break
else:
print(f"Amount must be between {MIN_BET} - {MAX_BET}.")
else:
print("Please enter a number.")
return amount
def main():
balance = deposit()
lines = get_number_of_lines()
while True:
bet = get_bet()
total_bet = bet * lines
if total_bet > balance:
print (f"You do not have enough cash to pay the bet from your balance. Your current balance is {balance}")
else:
break
slots = get_slot_machine_spin (ROWS, COLS, symbol_count)
print_slot_machine(slots)
winnings, winning_lines = check_winnings(slots, lines, bet, symbol_value)
print(f"You won {winnings}")
print(f"You won on", *winning_lines) #splat or unpack operator
return
main()
The output at runtime is:
What would you like to deposit?100
Enter the number of lines to bet on (1-3? 3
How much would you like to bet on each line?3
A | B | D
B | C | C
D | A | C
But then I get this traceback...
UnboundLocalError Traceback (most recent call last)
/var/folders/v_/yq26pm194xj5ckqy8p_njwc00000gn/T/ipykernel_54333/4159941939.py in <module>
122 return
123
--> 124 main()
/var/folders/v_/yq26pm194xj5ckqy8p_njwc00000gn/T/ipykernel_54333/4159941939.py in main()
117 slots = get_slot_machine_spin (ROWS, COLS, symbol_count)
118 print_slot_machine(slots)
--> 119 winnings, winning_lines = check_winnings(slots, lines, bet, symbol_value)
120 print(f"You won {winnings}")
121 print(f"You won on", *winning_lines) #splat or unpack operator
/var/folders/v_/yq26pm194xj5ckqy8p_njwc00000gn/T/ipykernel_54333/4159941939.py in check_winnings(columns, lines, bet, values)
23
24 def check_winnings(columns, lines, bet, values):
---> 25 winnings - 0
26 winning_lines = []
27 for line in range(lines):
UnboundLocalError: local variable 'winnings' referenced before assignment
How do I unpack this?
Did you mean to write
winnings = 0
instead of
winnings - 0
What you wrote subtracts zero from the winnings variable which does not exist yet.

How can I fix this "ValueError: not enough values to unpack (expected 3, got 2)"?

Please help me with my assignment!
My goal is that the user can choose whose grade he/she wants to see in a certain subject. The output should be something like this:
Name: Mary , Math Grade: 98
This is what I have so far:
N = int(input("Please enter number of students: "))
while (N < 2 or N > 10):
N = int(input("Please only enter 2 - 10 students: "))
name = []
math_grade = []
science_grade = []
while (N != 0):
name.append(input('Enter name:'))
math_grade.append(input('Enter grade in math:'))
science_grade.append(input('Enter grade in science:'))
N = N - 1
record = []
record.append(name)
record.append(math_grade)
record.append(science_grade)
Class_Record = {}
for name, math_grade, science_grade in record:
Class_Record[name] = {"name": name, "math grade": math_grade, "science grade": science_grade }
I keep getting the value error at that point. I also don't know how to print it to get what I want.
If you can help me fix the error and tell me how I can print my desired output, I would be really grateful!!!
The problem is how you've organized the record list.
This line of code expects each item in record to be a sub-list with three items: name, math grade, and science grade.
for name, math_grade, science_grade in record
So it's expecting record to be something like this:
record = [
["Jim", "B", "C"],
["Mary", "A", "B"],
]
But instead, you made record to be a sub-list of names, then a sub-list of math grades, then a sub-list of science grades:
record = [
["Jim", "Mary"],
["B", "A"],
["C", "B"]
]
So when the code pulls the first item in record, it's a list of only two items, where you told it to expect three. (If you had three students, the code would have "worked", but not the way you wanted.)
So you either have to change how you put things into record to match how you're pulling them out, or change how you're pulling them out.
In fact, it seems like record is just a temporary variable that is only used to build Class_Record. If that's true, you could just build Class_Record directly:
Class_Record = {}
while (N != 0):
name = input('Enter name:')
math_grade = input('Enter grade in math:')
science_grade = input('Enter grade in science:')
Class_Record[name] = {'math_grade': math_grade, 'science_grade': science_grade)
N = N - 1
N = int(input("Please enter number of students: "))
while (N < 2 or N > 10):
N = int(input("Please only enter 2 - 10 students: "))
Class_Record = []
while (N != 0):
name = input('Enter name:')
math_grade = input('Enter grade in math:')
science_grade = input('Enter grade in science:')
temp = {'name': name, 'math grade': math_grade, 'science grade': science_grade}
Class_Record.append (temp)
N = N - 1
print (Class_Record)
You can change your code like below
N = int(input("Please enter number of students: "))
while (N < 2 or N > 10):
N = int(input("Please only enter 2 - 10 students: "))
Class_Record={}
while (N != 0):
name = input('Enter name:')
math_grade = input('Enter grade in math:')
science_grade = input('Enter grade in science:')
Class_Record[name]={"name": name, "math grade": math_grade, "science grade": science_grade}
N = N - 1
print(Class_Record)

Loop to add more input

I have 3 more cars that I have but I need to know how to loop things like the car input so it will allow you to input it again if you do the wrong input same thing with the extras so they have to be either 1 or 0.
print("===================================================")
print("==============Car Finance Calculations=============")
print(" Choose your veicle: ")
print(" SUV type 1 ")
print(" Hatch type 2 ")
print(" Sedan type 3 ")
print("===================================================")
caaaaaaaar = int(input(" Please enter Which car you want to finance: "))
years = int(input(" enter years of loan either 3 or 4 or 5 Years: "))
if caaaaaaaar == 1:
carsvalue = int(input("Please enter you cars value: "))
residual = carsvalue * 0.30
financing = carsvalue - residual
print(" financing value for the car is: ", round(financing,2))
print(" Intrest rate is 9% ")
n = years * 12
r = 9 / (100 * 12)
Financingcost = financing * ((r*((r+1)**n))/(((r+1)**n)-1))
print(" Your Montly financing rate is: ", round(Financingcost,2))
print("================================================================================")
print("Please Choose extras: ")
print("======================================================")
print(" If you would like fuel type 1 if not type 0")
print(" If you would like insurance type 1 if not type 0")
print(" if you would like Maintenance type 1 if not type 0")
print("======================================================")
if caaaaaaaar == 1:
x, y, z = [int(x) for x in input("Enter Your extras with spaces:").split()]
print("=======================================")
if x == 1:
print("Yes you want fuel")
fuelcost = 80 * 4.33
print("fuel cost is", round(fuelcost,2))
if x == 0:
print("you dont want fuel as an extra")
fuelcost = 0
print("Fuel cost is: ", fuelcost)
print("=======================================")
if y == 1:
print("yes you want insurance")
insurancecost = (1200 / 12)
print("Insurance cost is: ", round(insurancecost,2))
if y ==0:
print("you dont want insurance")
insurancecost = 0
print("insurance cost is: ",insurancecost)
print("=======================================")
if z == 1:
print("yes you want maintenance")
maintenancecost = (100 * 1)
print("Maintenance cost is: ", round(maintenancecost,2))
if z == 0:
print("you dont want maintenance")
maintenancecost = 0
print("maintenance cost is: ",maintenancecost)
print("=======================================")
total_cost_for_extras = fuelcost + maintenancecost + insurancecost
print("Total cost for the selected extras is: ", round(total_cost_for_extras,2))
TOTALFOREVERYTHING = total_cost_for_extras + Financingcost
print("Total monthly financing rate is: ", round(TOTALFOREVERYTHING,2))
You want to use a while loop.
Like this:
carsEntered = 0
while (carsEntered <= 4):
caaaaaaaar = int(input(" Please enter Which car you want to finance: "))
years = int(input(" enter years of loan either 3 or 4 or 5 Years: "))
carsEntered += 1
You could also use a for loop instead but that depends on what you want to do.
As per my understanding of the question you want to run an iteration until the user gives the right answer.
In that case, you can use flag variable in while.
flag = False
while(flag is False):
if(condition_statisfied):
flag = True
I suggest that you put your vehicle types in a dictionary:
vehicle_type_dict = {
1: "SUV type",
2: "Hatch type",
3: "Sedan type"
}
and do a while-loop to check if your input is in the dictionary:
while True:
caaaaaaaar = int(input(" Please enter Which car you want to finance: "))
if caaaaaaaar not in vehicle_type_dict:
continue #loop again if input not in the dictionary
#read next line of code if input is in the dictionary
#do something below if input is correct
years = int(input(" enter years of loan either 3 or 4 or 5 Years: "))
break #end loop
My recommendation is to take a functional approach to this problem. You are calling int(input()) multiple times and want to validate the user input before proceeding on to the next lines each time. You can do this in a function that will continue to loop until the input is confirmed as valid. Once the input is validated, you can exit the function's frame by returning the value using the return key word.
# This is the function definition.
# The code in this function does not execute until the function is called.
def prompt_int(
text,
minimum=0,
maximum=1,
error="The value you entered is not valid try again."
):
# when the function is called it will start a second while loop that will keep looping
# until valid input is entered
while True:
try:
val = int(input(text))
if minimum <= val <= maximum:
return val
raise ValueError
except ValueError:
print(error)
# This is the outer while loop. It will keep looping forever if the user so chooses.
while True:
# instead of calling print() a bunch one option is to assign a docstring to a variable
car_prompt = '''
===================================================
==============Car Finance Calculations=============
Choose your veicle:
SUV: 1
Hatch: 2
Sedan: 3
===================================================
Please enter the number for the car you want to finance or 0 to exit:\n
'''
# This is where we first call the function.
# Our docstring will be passed into the function to be used as a prompt.
# We also pass in some args for maximum and minimum params
caaaaaaaar = prompt_int(car_prompt, 0, 3)
# 0 is false so we can exit the while loop if the user enters 0
if not caaaaaaaar:
break
year_prompt = "Enter years of the car loan (3, 4 or 5):\n"
years = prompt_int(year_prompt, 3, 5)
if caaaaaaaar == 1:
val_prompt = "Please enter you cars value:\n"
carsvalue = prompt_int(val_prompt, 0, 2147483647)
residual = carsvalue * 0.30
financing = carsvalue - residual
print("Financing value for the car is: ", round(financing, 2))
print("Intrest rate is 9% ")
n = years * 12
r = 9 / (100 * 12)
Financingcost = financing * ((r * ((r + 1) ** n)) / (((r + 1) ** n) - 1))
print(" Your Montly financing rate is: ", round(Financingcost, 2))
print("================================================================================")
print("Please Choose extras: ")
print("======================================================")
x = prompt_int("If you would like fuel type 1 else type 0:\n")
y = prompt_int("If you would like insurance type 1 else type 0:\n")
z = prompt_int("If you would like Maintenance type 1 else type 0:\n")
print("======================================================")
if x == 1:
print("Yes you want fuel")
fuelcost = 80 * 4.33
print("fuel cost is", round(fuelcost, 2))
else:
print("you dont want fuel as an extra")
fuelcost = 0
print("Fuel cost is: ", fuelcost)
print("=======================================")
if y == 1:
print("yes you want insurance")
insurancecost = (1200 / 12)
print("Insurance cost is: ", round(insurancecost, 2))
else:
print("you dont want insurance")
insurancecost = 0
print("insurance cost is: ", insurancecost)
print("=======================================")
if z == 1:
print("yes you want maintenance")
maintenancecost = (100 * 1)
print("Maintenance cost is: ", round(maintenancecost, 2))
else:
print("you dont want maintenance")
maintenancecost = 0
print("maintenance cost is: ", maintenancecost)
print("=======================================")
total_cost_for_extras = fuelcost + maintenancecost + insurancecost
print("Total cost for the selected extras is: ", round(total_cost_for_extras, 2))
TOTALFOREVERYTHING = total_cost_for_extras + Financingcost
print("Total monthly financing rate is: ", round(TOTALFOREVERYTHING, 2))
elif caaaaaaaar == 2:
# Put your code for car 2 in this block.
# If it is like car 1 code except the value of a few variables
# then make another func
pass
else:
# Car 3 code...
pass

How can I condense this simple python program to make it more efficient?

This is just a simple game I tried to put together that asks you a couple questions and then automatically formats a new passcode out of the answers.
Since I am a beginner I'd like to know of some techniques I could use that would increase the efficiency of this code, and maybe remove the crazy amount of functions I've declared. Thank You!
minimum = 3
maximum = 10
name = input("What is your name? ")
def nameInput():
if len(name) < minimum:
print("Name is too small")
return nameInput()
elif len(name) > maximum:
print("Name is too large")
return nameInput()
nameInput()
food = input("What is your favorite food? ")
def foodInput():
if len(food) < minimum:
print("Enter a food name longer than " + (food))
return foodInput()
elif len(food) > maximum:
print("Enter a food name shorter than " + (food))
return foodInput()
foodInput()
birthday = input("What is your date of birth? (mmddyyyy) ")
nameIndex = name[0:2]
foodIndex = food[2: ]
birthIndex = birthday[0:3]
passcode = nameIndex + foodIndex + birthIndex
print("Your password is " + passcode)
If you're after brevity, try to use a single function multiple times rather than multiple functions a single time
def get_input(variable_name, min_size, max_size, begin, end):
data = input("What is your {}? ".format(variable_name))
if len(data) < min_size:
raise ValueError('{} is too small'.format(variable_name.capitalize()))
elif len(data) > max_size:
raise ValueError('{} is too big'.format(variable_name.capitalize()))
return data[begin:end]
name_index = get_input("name", 3, 10, 0, 2)
food_index = get_input("food", 3, 10, 2, 100)
birth_index = get_input("date of birth (mmddyyyy)", 3, 10, 0, 3)
passcode = name_index + food_index + birth_index
print("Your passcode is", passcode)

Condition "and", "or"

I have a problem with my condition. I would like the variable tabPoint to be between 10 and 100.
Here is my code:
def demand(nb):
tabName = [];
tabPoint = [];
for i in range(nb):
tabName.append(raw_input("Name of the jumper " + str(i+1) + " : "))
tabPoint.append(input("1st jump " + tabName [i] + " The number must be between 10 and 100: " ));
if int (tabPoint[i] < 5 ) and int (tabPoint[i] > 100):
tabPoint.append(input("The number must be between 10 and 100 " ));
return tabName, tabPoint;
name, point = demand(3)
print(name, point)
You have misplaced your parentheses. What you want as an int is tabPoint[i], not tabPoint[i] < 5.
So the correct form is
if int(tabPoint[i]) > 5 and int(tabPoint[i]) < 100:
tabPoint.append(input("The number must be between 10 and 100 " ))
You can also use the short version that accomplishes the same:
if 5 < int(tabPoint[i]) < 100:
tabPoint.append(input("The number must be between 10 and 100 "))
Try this:
def demand(nb):
tabName = []
tabPoint = []
for i in range(nb):
tabName.append(input("Name of the jumper "+str(i+1)+": "))
tabPoint.append(0)
# Until a valid entry is made, this prompt will occur
while tabPoint[i] < 10 or tabPoint[i] > 100:
tabPoint[i] = (int(
input("1st jump "+tabName[i]+" The number must be between 10 "
"and 100: ")))
return dict(zip(tabName, tabPoint)) # Returning a dictionary mapping name to point
Say you wanted to print each name and point after this, you could implement something like:
info = demand(3)
for name, point in info.items():
print(f"Name: {name} Point: {point}")

Categories

Resources