How to repeat blocks of code in Python - python

I've created a code that allows a user to view the average score of the values that are in the file. In Example the Text File would look like the following:
Text File For Class 1: it is similar for each text file ; 2 and 3. just different names and values
Matt 2
Sid 4
Jhon 3
Harry 6
There are 3 classes altogether in which the user is prompted to choose which class they want to preview.
Code:
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
main_menu()
option = input("option [avg]: ")
option_class = input("class: ")
one = "1.txt"
two = "2.txt"
three = "3.txt"
if option.lower() == 'avg' and option_class == '1':
with open(one) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '2':
with open(two) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '3':
with open(three) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
Question
If i wanted to Keep Repeating the code above so that the user can keep using it until they want to exit. so, is it possible to put the code into a while loop and only stop the code if the user wants to, i.e the user is prompted if they want to choose another option and class.
NB: there will be other options such as alphabetical order however right now i only want to know how to do it for the average section.

Best thing you can do is to make a loop for user input and write a function for listing the file.
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
main_menu()
option = ""
options = ["1", "2", "3"]
one = "1.txt"
two = "2.txt"
three = "3.txt"
def read_text_file(file): # standalone function for viewing files to reduce duplicate code
file += ".txt"
with open(file) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
while True:
option = input("option [avg]: ").lower()
if option == "exit":
break # checks if user want to exit a program
else:
option_class = input("class: ")
if option == 'avg' and option_class in options:
read_text_file(option_class)
else:
print("nothing to show, asking again")
print("end of program")

As I mentioned in the comment section, you should leverage the power of functions here. By breaking down your components to manageable pieces, you actually afford yourself readability and flexibility. See code below, where I have two functions, one for averages and one for totals.
def get_class_average(class_number):
filename = "{0}.txt".format(class_number)
try:
with open(filename) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
return avg
except:
print "No file with that name found."
def get_class_total(class_number):
filename = "{0}.txt".format(class_number)
try:
with open(filename) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
return b
except:
print "No file with that name found."
def check_class_number(string_input):
try:
int(string_input)
return True
except ValueError:
return False
if __name__ == "__main__":
while True:
input_val = raw_input(
"Enter class number (enter 'exit' to quit program): ")
if input_val == 'exit':
break
if check_class_number(input_val): # If it's a valid class number.
method = raw_input("Enter method: ")
if method == 'avg':
avg = get_class_average(int(input_val))
print "The average of Class {0} is {1}".format(input_val, avg)
elif method == 'sum':
total = get_class_total(int(input_val))
print "The total of Class {0} is {1}".format(input_val, total)
else:
print "That is not a valid class number."
continue
Sample run:
The really fun part here is that you can even refactor get_class_average and get_class_total to be a single function that checks if the passed in method is avg or sum and returns the respective values from there (this is easily doable since you have practically the same lines of code for both functions, get_class_average just has an extra division involved).
Have fun.

Yes, you can just put your code within a while-loop and prompt the user for input:
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
# End main_menu()
one = "1.txt"
two = "2.txt"
three = "3.txt"
keepGoing = True
while(keepGoing):
main_menu()
option = input("option [avg]: ")
option_class = input("class: ")
if option.lower() == 'avg' and option_class == '1':
with open(one) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '2':
with open(two) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '3':
with open(three) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
# Prompt user for input on whether they want to continue or not:
while(True):
keepGoingStr = input("Would you like to continue? (Y/N)\n>>> ").lower()
if(keepGoingStr[0] == 'y'):
# Keep going
keepGoing = True
break
elif(keepGoingStr[0] == 'n')
# Stop
keepGoing = False
break
else:
print("Sorry, your input did not make sense.\nPlease enter either Y or N for yes or no.")
# end if
# end while - keep going input
# End While(keepGoing)
As mentioned in the comments, though, you should consider breaking up your code into functions.

Related

Why is the menu of my program stuck in an infinite loop?

I'm creating a program so that a track coach can easily pull up runners times as well as input them.
I'm trying to figure out why when I start my program, it runs the function 'MENU', looping it.
user_input = 0
print('MENU')
print('1 - Add runner data to file')
print('2 - Display runners and their times')
print('3 - Calculate the average run time')
print('4 - Display the fastest time')
print('5 - EXIT')
print()
def MENU():
user_input = int(input('Enter your Menu choice >> '))
return -1
def DATA(f_runner, f_time):
f_runner = str(input('Enter runners name >> '))
f_time = str(input('Enter the runners time in hours >> '))
print('Runners data entered into the file.')
f = open('myFile.txt', 'w')
f.write(str(f_runner))
f.write(str(f_time))
f.close()
return f_runner, f_time
def DISPLAY():
contents = f.readlines()
f = open('myFile.txt')
print(contents)
runners_data = 0
runner = 0
runner_time = 0
average_time = 0
file_runner = ''
file_time = 0.0
contents = ''
program_exit = False
menu_start = 0
while program_exit == False:
menu_start = MENU()
while user_input > 0 and user_input < 6:
if user_input == '1':
DATA(file_runner, file_time)
elif user_input == '2':
Display()
elif user_input == '5':
program_exit = True
You are returning -1 instead of user_input in MENU()
Alongside what Samraj said, I believe it's also because your if statement is comparing if the user input is returned as a string, when you're expecting the user to return an int.
You could just remove it from the bottom and have it run inside menu and just call MENU().
Try this and edit it to what you need
print('MENU')
print('1 - Add runner data to file')
print('2 - Display runners and their times')
print('3 - Calculate the average run time')
print('4 - Display the fastest time')
print('5 - EXIT')
print()
def MENU():
the_input = int(input('Enter your Menu choice >> '))
if the_input == 1:
print("hello")
DATA(file_runner, file_time)
elif the_input == 2:
Display()
elif the_input == 5:
exit()
return the_input
def DATA(f_runner, f_time):
f_runner = str(input('Enter runners name >> '))
f_time = str(input('Enter the runners time in hours >> '))
print('Runners data entered into the file.')
f = open('myFile.txt', 'w')
f.write(str(f_runner))
f.write(str(f_time))
f.close()
return f_runner, f_time
def DISPLAY():
contents = f.readlines()
f = open('myFile.txt')
print(contents)
runners_data = 0
runner = 0
runner_time = 0
average_time = 0
file_runner = ''
file_time = 0.0
contents = ''
program_exit = False
menu_start = 0
MENU()

Cannot use a returned value

New to python, probably a dumb question. It's saying the "addAns" in the last line is undefined. How do I get it to use the value from the add function
def add (addL):
c = 0
while c < 4:
x = input("Type a number to add. " )
c += 1
addL.append(x)
if x == "end":
c += 5
addL.remove("end")
addStep = [int(i) for i in addL]
addAns = sum(addStep)
return addAns
userIn = input("What function would you like to perform? ")
if userIn == 'add':
add(addL)
print(addAns)
You should assign the output of the function:
if userIn == 'add':
addAns = add(addL)
print(addAns)
It doesn't need to be the same name, the scopes are independent:
if userIn == 'add':
output = add(addL)
print(output)
You can also directly use the output in print:
if userIn == 'add':
print(add(addL))

While loop not terminating when the condition has been satisified

While programming in Python I got stuck in a case where the while loop is not terminating even after the condition is being satisified then also
the code is as follows:
print('--- Alex\'s Calculator ---')
print('1. ADDition')
print('2. SUBstraction')
print('3. MULtiply')
print('4. DIVide')
print('5. EXIT')
x = int(input())
command = ' Enter Your Two numbers To Perform The Operation : '
def ini():
a = int(input())
b = int(input())
return a, b
def resultoo():
result = ' Your Result after Performing The Operation from {} and {} is {}'
print(result.format(a,b,c))
print(' Want To Continue If Yes then Enter Your Choice else Press any number exept 1 - 4')
x = int(input())
while x < 5:
if x == 1:
print(command)
a, b = ini()
c = a + b
resultoo()
elif x < 5:
break
As kuro specified in the comment, x can't be seen by your while loop because it's local to resultoo().
To solve it easily just add :
return x
at the end of resultoo()
and
x = resultoo()
in your while loop
You can use global var to this, change the this:
def resultoo():
result = ' Your Result after Performing The Operation from {} and {} is {}'
print(result.format(a,b,c))
print(' Want To Continue If Yes then Enter Your Choice else Press any number exept 1 - 4')
x = int(input())
into:
def resultoo():
global x
result = ' Your Result after Performing The Operation from {} and {} is {}'
print(result.format(a,b,c))
print(' Want To Continue If Yes then Enter Your Choice else Press any number exept 1 - 4')
x = int(input())
Explnation:
x is a global argument, that will be the same out of the function closure, but not inside of it, the function has it own params, so if you want to change a global argument that is initalizing outside the function, you will need to call the global statement before, that will make x the global x
When option 5 is entered you want to exit.
I added
import sys
and changed
elif x < 5:
to
elif x == 5:
and added
sys.exit(0)
I also added the getMenu() function
This is the complete code that is working in my editor:
import sys
def ini():
command = ' Enter Your Two numbers To Perform The Operation : '
print(command)
a = int(input())
b = int(input())
return a, b
def resultoo(a, b, c):
result = ' Your Result after Performing The Operation from {} and {} is {}'
print(result.format(a, b, c))
def getMenu(x):
if x == 0:
print("Choose menu item")
x = int(input())
elif x != 0:
print(' Want To Continue If Yes then Enter Your Choice else Press any number exept 1 - 4')
x = int(input())
return x
def main():
x = 0
while x < 5:
print('\n\n1. ADDition')
print('2. SUBstraction')
print('3. MULtiply')
print('4. DIVide')
print('5. EXIT\n')
x = getMenu(x)
if x == 1:
a, b = ini()
c = a + b
resultoo(a, b, c)
elif x == 5:
sys.exit(0)
else:
print("No valid menu item")
if __name__ == '__main__':
print('----------------------------------------------------------------------------------------------------------')
print('-------------------------------------------- Alex\'s Calculator -------------------------------------------')
main()
I also formatted your code (alt+Enter in Pycharm) to comply to PEP8 standards ;)

Incorrect code is being called in 'if/elif/else' statement

I'm making an interest calculator that does compound and simple interest. However, the if statement always runs the simple interest script regardless of input.
I have tried changing variables to strings, integers, and floats. I have tried changing variable names, I have tried removing the first block of code entirely. What the heck is wrong with it???
start = input("simple or compound: ")
if start == "simple" or "Simple":
a = float(input('Starting balance: '))
b = float(input('Rate: '))
c = int(input('Years: '))
final = int(a+((a*b*c)/100))
print(final)
elif start == "compound" or "Compound":
d = float(input('Starting balance: '))
e = float(input('Rate: '))
f = int(input('Years: '))
final2 = int(d*(1+(e/100))**f)
print(final2)
else:
d = float(input('Starting balance: '))
e = float(input('Rate: '))
f = int(input('Years: '))
final3 = int(d*(1+(e/100))**f)
print(final3)
If I input Starting balance as 5000, rate as 5, and years as six into simple it gives 6500. But the same result occurs when I call compound.
This expression is not correct:
start == "simple" or "Simple"
should be
start == "simple" or start "Simple"
code below worked:
start = input("simple or compound: ")
if start == "simple" or start == "Simple":
# print("simple")
a = float(input('Starting balance: '))
b = float(input('Rate: '))
c = int(input('Years: '))
final = int(a+((a*b*c)/100))
print(final)
elif start == "compound" or start == "Compound":
# print("compound")
d = float(input('Starting balance: '))
e = float(input('Rate: '))
f = int(input('Years: '))
final2 = int(d*(1+(e/100))**f)
print(final2)
else:
# print("unknown")
d = float(input('Starting balance: '))
e = float(input('Rate: '))
f = int(input('Years: '))
final3 = int(d*(1+(e/100))**f)
print(final3)
Because of operator precedence
if start == "simple" or "Simple"
is evaluated as
if (start == "simple") or "Simple"
The (...) part is True if the user entered "simple", but the "Simple" part is always True.

determinating if the input is even or odd numbers

Hello I am trying to write a program in python that asks the user to input a set of numbers of 1's and 0's and I want the program to tell me if I have and even number of zeros or an odd number of zeros or no zero's at all. Thanks for your help!!
forstate = "start"
curstate = "start"
trans = "none"
value = 0
print "Former state....:", forstate
print "Transition....:", trans
print "Current state....", curstate
while curstate != "You hav and even number of zeros":
trans = raw_input("Input a 1 or a 0: ")
if trans == "0" and value <2:
value = value + 1
forstate = curstate
elif trans == "1" and value < 2:
value = value + 0
forstate = curstate
curstate = str(value) + " zeros"
if value >= 2:
curstate = "You have and even number of zeros"
print "former state ...:", forstate
print "Transition .....:", trans
print "Current state....", curstate
Looks like you're trying to do a finite state machine?
try:
inp = raw_input
except NameError:
inp = input
def getInt(msg):
while True:
try:
return int(inp(msg))
except ValueError:
pass
START, ODD, EVEN = range(3)
state_next = [ODD, EVEN, ODD]
state_str = ['no zeros yet', 'an odd number of zeros', 'an even number of zeros']
state = START
while True:
num = getInt('Enter a number (-1 to exit)')
if num==-1:
break
elif num==0:
state = state_next[state]
print 'I have seen {0}.'.format(state_str[state])
Edit:
try:
inp = raw_input
except NameError:
inp = input
START, ODD, EVEN = range(3)
state_next = [ODD, EVEN, ODD]
state_str = ['no zeros yet', 'an odd number of zeros', 'an even number of zeros']
def reduce_fn(state, ch):
return state_next[state] if ch=='0' else state
state = reduce(reduce_fn, inp('Enter at own risk: '), START)
print "I have seen " + state_str[state]
It sounds like homework, or worse an interview questions, but this will get you started.
def homework(s):
counter = 0
if '0' in s:
for i in s:
if i == '0':
counter = counter + 1
return counter
don't forget this part over here
def odd_or_even_or_none(num):
if num == 0:
return 'This string contains no zeros'
if num % 2 == 0
return 'This string contains an even amount of zeros'
else:
return 'This string contains an odd amount of zeros'
if you call homework and give it a string of numbers it will give you back the number of 0
homework('101110101')
now that you know how many 0s you need to call odd_or_even_or_none with that number
odd_or_even_or_none(23)
so the solution looks like this
txt = input('Feed me numbers: ')
counter = str( homework(txt) )
print odd_or_even_or_none(counter)
try:
inp = raw_input
except NameError:
inp = input
zeros = sum(ch=='0' for ch in inp('Can I take your order? '))
if not zeros:
print "none"
elif zeros%2:
print "odd"
else:
print "even"
The simple solution to your problem is just to count the zeros, then print a suitable message. num_zeros = input_stream.count('0')
If you're going to build a finite state machine to learn how to write one, then you'll learn more writing a generic FSM and using it to solve your particular problem. Here's my attempt - note that all the logic for counting the zeros is encoded in the states and their transitions.
class FSMState(object):
def __init__(self, description):
self.transition = {}
self.description = description
def set_transitions(self, on_zero, on_one):
self.transition['0'] = on_zero
self.transition['1'] = on_one
def run_machine(state, input_stream):
"""Put the input_stream through the FSM given."""
for x in input_stream:
state = state.transition[x]
return state
# Create the states of the machine.
NO_ZEROS = FSMState('No zeros')
EVEN_ZEROS = FSMState('An even number of zeros')
ODD_ZEROS = FSMState('An odd number of zeros')
# Set up transitions for each state
NO_ZEROS.set_transitions(ODD_ZEROS, NO_ZEROS)
EVEN_ZEROS.set_transitions(ODD_ZEROS, EVEN_ZEROS)
ODD_ZEROS.set_transitions(EVEN_ZEROS, ODD_ZEROS)
result = run_machine(NO_ZEROS, '01011001010')
print result.description

Categories

Resources