How to recall a function until invalid input? - python

I'm new to python, and I was wondering how I could recall a function until the user gives invalid input.
Here's a sample of code:
start = input("For sum of squares, type 'squares'. For sum of cubes, type 'cubes'. "
"\nIf you would like to raise a number to something other than 'squares' or 'cubes', type 'power'. "
"\nIf you would like to exit, type 'exit':")
def main_function(start):
while start.lower() != "exit":
if start.lower() in "squares":
initial = input("What is the initial constant for the sum of the squares: ")
terms = input("Number of terms: ")
if start.lower() in "cubes":
initial = input("What is the initial constant for the the sum of the cubes: ")
terms = input("Number of terms: ")
if start.lower() in "power":
initial = input("What is the initial constant for the the sum: ")
terms = input("Number of terms: ")
else:
print("Program halted normally.")
quit()
main_function(start)
What I am trying to get it to do is to reprompt 'start' if the user inputs a proper input, and then get it to run through the function again. I have tried putting 'start' within the function above and below the 'else' statement, but it never accepts the new input.

I would do it like this, define the start input in a method and call it inside the loop, when it's equal to "exit" than break the loop.
Also use elif, this way if the first condition statement is True than you won't check the others, unless that what you want of course.
def get_start_input():
return input("For sum of squares, type 'squares'. For sum of cubes, type 'cubes'. "
"\nIf you would like to raise a number to something other than 'squares' or 'cubes', type 'power'. "
"\nIf you would like to exit, type 'exit':")
def main_function():
while True:
start = get_start_input()
if start.lower() == "squares":
initial = input("What is the initial constant for the sum of the squares: ")
terms = input("Number of terms: ")
elif start.lower() == "cubes":
initial = input("What is the initial constant for the the sum of the cubes: ")
terms = input("Number of terms: ")
elif start.lower() == "power":
initial = input("What is the initial constant for the the sum: ")
terms = input("Number of terms: ")
elif start.lower() == "exit":
print("Program halted normally.")
break
main_function()
EDIT:
As dawg wrote in comment, it's preferred to use here == instead of in because you can have several matches and ambiguous meanings.

Related

How to calculate average and range after input into list?

I need some help regarding calculating averages and ranges. I am using built-in functions such as sum(), len(), etc. and cannot seem to calculate the average or range. I am using it to write a small piece of code for fun but cannot seem to get it to work. any help is much appreciated. Thank you!
x = 1
number_list = []
while x == 1:
input_number = input("PLease input an integer")
if str.isdigit(input_number) == True:
number_list.append(input_number)
else:
print("Please input a valid integer only.")
continueornot = input("Would you like to continue adding data? PLease input 'Yes' to continue, and anything else to quit.")
if continueornot == 'Yes':
x = 1
else:
print("Here is the maximum number:", max(number_list))
print("Here is the minimum number:", min(number_list))
print("Here is the count:", len(number_list))
print("Here is the average:" + sum(number_list) / len(number_list))
print("Here is the range:", range(number_list))
quit()
Change
if str.isdigit(input_number) == True:
number_list.append(input_number)
to
if input_number.isdigit():
number_list.append(int(input_number))
The error is because you're trying to do those operations on a list of strings.
You can also remove the check against True since that is implicitly checking the truthiness and since input_number is already a str, you can call the isdigit() method directly.
The problem is that you are appending strings to the list rather than integers and then you are applying arithmetic operations on it. So first you should convert the input number to int type.
Secondly range function will not give you the range of a list rather then it returns a sequence.
x = 1
number_list = []
while x == 1:
input_number = input("PLease input an integer")
if str.isdigit(input_number) == True:
input_number=int(input_number)
number_list.append(input_number)
else:
print("Please input a valid integer only.")
continueornot = input("Would you like to continue adding data? PLease input 'Yes' to continue, and anything else to quit.")
if continueornot == 'Yes':
x = 1
else:
print("Here is the maximum number:", max(number_list))
print("Here is the minimum number:", min(number_list))
print("Here is the count:", len(number_list))
print("Here is the average:" , sum(number_list) / len(number_list))
print("Here is the range:", max(number_list)-min(number_list))

Python function returns None after checking if user input is valid

I've just started learning programming some time ago and been playing with Python a bit. I wrote a small program that rolls dice based on user input (number of sides on the die and number of dice). Here's the code:
from random import randrange
def number_of_sides():
n = input("How many sides? ") # Get input from the user
if n.isdigit(): # Check if the input is a digit
n = int(n) # If it is, turn it into an integer
return n # And return the value of n
else:
print("Invalid input. ") # If test returns false, rerun function
number_of_sides()
def number_of_dice():
m = input("How many dice? ") # Get input from the user
if m.isdigit(): # Check if the input is a digit
m = int(m) # If it is, turn it into an integer
return m # And return the value of m
else:
print("Invalid input. ") # If test returns false, rerun function
number_of_dice()
def play_again() -> object: # Checks if user answered yes or no, then reruns everything or exits with exit code 0
answ = input("Do you want to play again?(yes/no) ")
if answ == "yes":
dice_roll()
elif answ == "no":
print("Ok then")
return True
else:
print("Input invalid, trying again")
play_again()
def dice_roll(): # sides - for number of sides, dice - for number of dice.
sides = number_of_sides() # Whatever number the function returns
dice = number_of_dice() # Whatever number the function returns
results = [] # empty list, here is where results will be appended
for i in range(1, dice + 1): # That returns values for each dice specified in the dice variable
throw = randrange(1, sides + 1)
results.append(throw)
results_str = " | ".join(str(i) for i in results) # Turn the list into string, separate results with a pipe
print(results_str) # Print the results of throws
play_again() # Ask the user to play again
dice_roll()
Everything works ok when I provide valid input (so digits like 6 and 6 for sides and dice), it crashes, however, when I try providing invalid input first. For some reason the number_of_sides() and number_of_dice() functions return None when they're first fed invalid input and then crash the code in the for loop in the dice_roll() function:
How many sides? a
Invalid input.
How many sides? 6
How many dice? 6
Traceback (most recent call last):
File "<directory>/dice_roll.py", line 48, in <module>
dice_roll()
File "<directory>/dice_roll.py", line 41, in dice_roll
throw = randrange(1, sides + 1)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
Process finished with exit code 1
I tested these functions separately and they seem to be working fine. This snippet:
def number_of_sides():
n = input("How many sides? ")
if n.isdigit():
n = int(n)
print(n, ", ", type(n))
return n
else:
print(n, ", ", type(n))
number_of_sides()
Returns str if you provide a string and int if you provide it with digits. I would like to know what may be causing this weird behaviour.
The problem is that you are calling number_of_dice recursively, but you ignore its result. You should replace the recursive call with:
return number_of_dice()
or even better, get rid of recursion by using a simple while loop:
def number_of_dice():
while True:
m = input("How many dice? ") # Get input from the user
if m.isdigit(): # Check if the input is a digit
m = int(m) # If it is, turn it into an integer
return m # And return the value of m
else:
print("Invalid input. ")
The same, obviously, holds for the other function.
I seem that the functions number_of_sides() and number_of_dice() only return a valid value when the first input is correct otherwise they loop themselves but the new input will not be returned to the main function.
I think recursivity is not good in that case.
You could transform number_of_dices like this :
def number_of_sides():
nb_sides = input("How many sides? ")
while (nb_sides.isdigit())==False:
print("Invalid input. ")
nb_sides=input("How many sides? ")
return int(nb_sides)
For your information, you can also use :
import pdb
pdb.set_trace()
to pause the code in a specific line
"return" statement from your fail case is missing in the 2 statements
from random import randrange
def number_of_sides():
n = input("How many sides? ") # Get input from the user
if n.isdigit(): # Check if the input is a digit
n = int(n) # If it is, turn it into an integer
return n # And return the value of n
else:
print("Invalid input. ") # If test returns false, rerun function
return number_of_sides()
def number_of_dice():
m = input("How many dice? ") # Get input from the user
if m.isdigit(): # Check if the input is a digit
m = int(m) # If it is, turn it into an integer
return m # And return the value of m
else:
print("Invalid input. ") # If test returns false, rerun function
return number_of_dice()
def play_again() -> object: # Checks if user answered yes or no, then reruns everything or exits with exit code 0
answ = input("Do you want to play again?(yes/no) ")
if answ == "yes":
dice_roll()
elif answ == "no":
print("Ok then")
return True
else:
print("Input invalid, trying again")
play_again()
def dice_roll(): # sides - for number of sides, dice - for number of dice.
sides = number_of_sides() # Whatever number the function returns
dice = number_of_dice() # Whatever number the function returns
results = [] # empty list, here is where results will be appended
for i in range(1, dice + 1): # That returns values for each dice specified in the dice variable
throw = randrange(1, sides + 1)
results.append(throw)
results_str = " | ".join(str(i) for i in results) # Turn the list into string, separate results with a pipe
print(results_str) # Print the results of throws
play_again() # Ask the user to play again
dice_roll()

Why does the following code not follow the specified order?

I want it to say welcome, ask for the user input (a,b,c), validate the user input and if the validation returns that the input is reasonable then carry out the quadratic formula on a,b,c. I suspect the problem is in the while-loop. The program just welcomes, asks for input then says welcome again and so on.
from math import sqrt
def quadratic_formula(a,b,c):
a=float(a) #The quadratic formula
b=float(b)
c=float(c)
x1_numerator = -1*b + sqrt((b**2)-4*(a*c))
x2_numerator = -1*b - sqrt((b**2)-4*(a*c))
denominator = 2*a
x1_solution = x1_numerator/denominator
x2_solution = x2_numerator/denominator
print("x= "+str(x1_solution)+" , x= "+str(x2_solution))
def number_check(a,b,c,check): #carries out a check
a=float(a)
b=float(b)
c=float(c)
if (b**2)-4*a*c < 0:
print("The values you have entered result in a complex solution. Please check your input.")
check == False
else:
check == True
check = False
while check == False:
print("Welcome to the Quadratic Equation Calculator!")
a = input("Please enter the x^2 coefficient: ")
b = input("Please enter the x coefficient: ")
c = input("Please enter the constant: ")
number_check(a,b,c,check)
else:
quadratic_formula(a,b,c)
You are correct in your suspicion. You have a problem in your while loop. does not work the way your code assumes.
Instead you need to write something like:
def number_check(a,b,c): #carries out a check
a=float(a)
b=float(b)
c=float(c)
if (b**2)-4*a*c < 0:
print("The values you have entered result in a complex solution. Please check your input.")
check = False
else:
check = True
return check
check = False
print("Welcome to the Quadratic Equation Calculator!")
while check == False:
a = input("Please enter the x^2 coefficient: ")
b = input("Please enter the x coefficient: ")
c = input("Please enter the constant: ")
check = number_check(a,b,c)
quadratic_formula(a,b,c)
Note, that in addition to changing the while loop you also need to update number_check as input parameters are not updated in calling scope. Instead the function has to explicitly return the updated value.
Try using return, not attempting to modify a global variable.
There's a way to use global variables (see global statement), but it's not necessary for this code.
The check variable itself isn't really necessary, though
def number_check(a,b,c):
a=float(a)
b=float(b)
c=float(c)
return (b**2)-4*a*c >= 0 # return the check
while True:
print("Welcome to the Quadratic Equation Calculator!")
a = input("Please enter the x^2 coefficient: ")
b = input("Please enter the x coefficient: ")
c = input("Please enter the constant: ")
if not number_check(a,b,c):
print("The values you have entered result in a complex solution. Please check your input.")
else:
break # getting out of the loop
There are two problems with the way you're using the check variable in the number_check function.
First, you're not assigning new values to it, because you're using == (which tests equality) rather than =.
But also, since it's a parameter variable, it's local to the function. So assigning it inside the function does not modify the global variable that you test in the while loop. Rather than use a global variable, you can simply test the result of number_check directly, and use break when you want to end the loop.
If you make this change, you need to move the call to quadratic_formula out of the else: clause, because that's only executed when the while condition fails, not when we end the loop with break.
def number_check(a,b,c): #carries out a check
a=float(a)
b=float(b)
c=float(c)
if (b**2)-4*a*c < 0:
print("The values you have entered result in a complex solution. Please check your input.")
return False
else:
return True
while True:
print("Welcome to the Quadratic Equation Calculator!")
a = input("Please enter the x^2 coefficient: ")
b = input("Please enter the x coefficient: ")
c = input("Please enter the constant: ")
if number_check(a,b,c):
break
quadratic_formula(a,b,c)

How to find the mean of a list

I'm very new to python and trying to write some code so that the user enters something. If it's an integer it's sorted into the Numbers list, if it's a string it goes into the String list.
I want to be able to find the mean of all the numbers that are in the list and print out the result.
And in the String section I want to be able to print out everything within the string and its length.
User types 'save' to exit and if input is valid that's caught.
Numbers = []
String = []
while(True):
user_input = input("What's your input? ")
if user_input == "save":
break
elif user_input.isdigit():
Numbers.append(user_input)
for i in range(len(Numbers)):
Numbers[i] = int(Numbers[i])
print(sum(Numbers)/len(Numbers)
elif isinstance(user_input, str):
String.append(user_input)
print(String)
print (len(String)-1)
else:
print("Invalid input.")
break
#use isalpha to check enterted input is string or not
#isalpha returns a boolean value
Numbers = []
String = []
while(True):
user_input = input("input : ")
if user_input == "save":
break
elif user_input.isdigit():
Numbers.append(int(user_input))
print(sum(Numbers)/len(Numbers))
elif user_input.isalpha():
String.append(user_input)
print(String)
print (len(String))
else:
print("Invalid input.")
break
There is good thing called statistics.mean:
from statistics import mean
mean(your_list)
You are using Length, which has not been defined. I think what you wanted was
print(sum(Numbers)/len(Numbers))
and you probably don't want it inside the loop, but just after it (although that might be another typo).
I found other more convenient way to produce the mean: Use statistics model and output the mean.
#import useful packages
import statistics
#Create an empty list
user_list = []
#get user request
user_input = input("Welcome to the average game. The computer is clever enough to get the average of the list of numbers you give. Please press enter to have a try.")
#game start
while True:
#user will input their number into a the empty list
user_number = input("Type the number you want to input or type 'a' to get the average and quit the game:")
#help the user to get an average number
if user_number == 'a':
num_average = statistics.mean(user_list)
print("The mean is: {}.".format(num_average))
break #Game break
else:
user_list.append(int(user_number))
print(user_list)

Integrating a for loop into an if statement

This is kind of a double-barreled question, but it's got me puzzled. I currently have the following code:
from __future__ import division
import math
function = int(raw_input("Type function no.: "))
if function == 1:
a = float(raw_input ("Enter average speed: "))
b = float(raw_input ("Enter length of path: "))
answer= float(b)/a
print "Answer=", float(answer),
elif function == 2:
mass_kg = int(input("What is your mass in kilograms?" ))
mass_stone = mass_kg * 2.2 / 14
print "You weigh", mass_stone, "stone."
else: print "Please enter a function number."
Now, I'd like to have some kind of loop (I'm guessing it's a for loop, but I'm not entirely sure) so that after a function has been completed, it'll return to the top, so the user can enter a new function number and do a different equation. How would I do this? I've been trying to think of ways for the past half hour, but nothing's come up.
Try to ignore any messiness in the code... It needs some cleaning up.
It's better to use a while-loop to control the repetition, rather than a for-loop. This way the users aren't limited to a fixed number of repeats, they can continue as long as they want. In order to quit, users enter a value <= 0.
from __future__ import division
import math
function = int(raw_input("Type function no.: "))
while function > 0:
if function == 1:
a = float(raw_input ("Enter average speed: "))
b = float(raw_input ("Enter length of path: "))
answer = b/a
print "Answer=", float(answer),
elif function == 2:
mass_kg = int(input("What is your mass in kilograms?" ))
mass_stone = mass_kg * 2.2 / 14
print "You weigh", mass_stone, "stone."
print 'Enter a value <= 0 for function number to quit.'
function = int(raw_input("Type function no.: "))
You can tweak this (e.g., the termination condition) as needed. For instance you could specify that 0 be the only termination value etc.
An alternative is a loop that runs "forever", and break if a specific function number is provided (in this example 0). Here's a skeleton/sketch of this approach:
function = int(raw_input("Type function no.: "))
while True:
if function == 1:
...
elif function == 2:
...
elif function == 0:
break # terminate the loop.
print 'Enter 0 for function number to quit.'
function = int(raw_input("Type function no.: "))
Note: A for-loop is most appropriate if you are iterating a known/fixed number of times, for instance over a sequence (like a list), or if you want to limit the repeats in some way. In order to give your users more flexibility a while-loop is a better approach here.
You simply need to wrap your entire script inside a loop, for example:
from __future__ import division
import math
for _ in range(10):
function = int(raw_input("Type function no.: "))
if function == 1:
a = float(raw_input ("Enter average speed: "))
b = float(raw_input ("Enter length of path: "))
answer= float(b)/a
print "Answer=", float(answer),
elif function == 2:
mass_kg = int(input("What is your mass in kilograms?" ))
mass_stone = mass_kg * 2.2 / 14
print "You weigh", mass_stone, "stone."
else: print "Please enter a function number."
This will run your if statement 10 times in a row.
I'd try this:
while True:
function = ...
if function == 0:
break
elif ...

Categories

Resources