Removing values in lists by user input (Python) - python

First time poster and I am very new to programming in general, (so please go easy on me) although I have worked in the IT industry as a help desk technician and field engineer.
I am in my first year at university and and have been asked to add a section on to a program to allow the user to remove entries that they have inputted into a list.
This is my code.
values = []
def programMenu():
print('This program will accept values until 0 is entered.')
choice = continueChoice()
if choice == 'Y':
ages = collectValues()
print('There are ', len(values),' in the data set.')
print('The values are as follows:', end ='')
print(values)
else:
return
def continueChoice():
print('Would you like to continue(Y/N):', end ='')
choice = str(input()).upper()
print(choice)
while choice != 'Y' and choice != 'N':
print('Invalid option. Would you like to continue(Y/N):', end ='')
choice = str(input()).upper()
return choice
def collectValues():
values = []
while True:
print ('Please enter each value:', end ="")
valValue = (int(input()))
if (valValue ==0):
break
values.append(valValue)
return values
def removeValues():
print(values)
print('Would you like to delete any entries?')
reage = str(input()).upper()
while reage == 'Y':
print('Which ages would you like to remove')
delVal = (int(input()))
values.remove(delVal)
else:
programMenu()
programMenu()
removeValues()
I have been trying to solve this for two days but I am getting an error "ValueError: list.remove(x): x not in list"
I have tried writing the removeValues code at the end of the operation to add values, I have tried to move the values = [] call around etc and have had no luck.
I checked the removeValues definition was actually taking the input by editing to get the program to print the value the user entered that they wished to be removed and that worked.
Any help is appreciated, I've only been coding a few months and I have emailed my lecturer but giving what's happening in the world at the moment the university are understaffed.
Thanks in advance.

before deleting the value from the list you need to add a if condition to check if value is present in the list or not for example:
if delVal in values:
values.remove(delVal)
else:
print('Value Not Found in the list')
and your while loop is in infinite loop as value of reage = 'Y' and you are not changing it inside the loop to stop.
you can use if statement instead of while.
def removeValues():
print(values)
print('Would you like to delete any entries?')
reage = str(input()).upper()
# if reage == 'Y'
if reage == 'Y':
print('Which ages would you like to remove')
delVal = (int(input()))
# check if delVal is present in the list or not
if delVal in values:
values.remove(delVal)
print('Deleted Age : '+ str(delVal))
print(values)
# if not then print the msg.
else:
print(str(delVal)+' Not Found in the list: ',str(values))
# you can uncomment the below code to again call removeValues function to ask for correct value to delete
#removeValues()
# if reage is not equal to 'Y' then it calls the programMenu again.
else:
programMenu()

You are not able to remove it because you are initializing the values in collectValues function each time. So the list is storing any value - just comment on this line and should work. Anyway, you also need to have exit criteria for each other functions.
values = []
def programMenu():
print('This program will accept values until 0 is entered.')
choice = continueChoice()
if choice == 'Y':
ages = collectValues()
print('There are ', len(values),' in the data set.')
print('The values are as follows:', end ='')
print(values)
else:
return
def continueChoice():
print('Would you like to continue(Y/N):', end ='')
choice = str(input()).upper()
print(choice)
while choice != 'Y' and choice != 'N':
print('Invalid option. Would you like to continue(Y/N):', end ='')
choice = str(input()).upper()
return choice
def collectValues():
#values = []
while True:
print ('Please enter each value:', end ="")
valValue = (int(input()))
if (valValue ==0):
break
values.append(valValue)
return values
def removeValues():
print(values)
print('Would you like to delete any entries?')
reage = str(input()).upper()
while reage == 'Y':
print('Which ages would you like to remove')
delVal = (int(input()))
values.remove(delVal)
else:
programMenu()
programMenu()
removeValues()

There are a few things that can be improved but I will try to keep the interface more or less the same.
The biggest issue is that functions in python have their own scope. That is, when you create a variable or list in a function, it is not shared in other functions.
What you need to do instead, (i think you had the right idea), is to create the list outside the functions and pass a reference to it as a parameter to each function:
values = []
def programMenu(values):
print('This program will accept values until 0 is entered.')
choice = continueChoice()
if choice == 'Y':
temp = collectValues()
values += temp # Append new values elementwise
print('There are ', len(values), ' in the data set.')
print('The values are as follows:', end='')
print(values)
else:
return
def removeValues(values):
print(values)
print('Would you like to delete any entries? (Y to continue)')
while str(input()).upper() == 'Y':
print('Which ages would you like to remove')
delVal = (int(input()))
values.remove(delVal)
print('Would you like to delete any entries? (pressY to continue)')
else:
programMenu(values)
programMenu(values)
removeValues(values)
The above functions need a reference to the initial list in order to manipulate it. Finally, a small change, in the removeValues() function, i moved the input in the while loop so that the question persists.
def collectValues():
values = [] # Not the same "values" list (not passed from reference)
while True:
print ('Please enter each value:', end="")
valValue = (int(input()))
if (valValue ==0):
break
values.append(valValue)
return values
If you have noticed, the collectValues() function does not need a reference since it only gets new values and later adds them to the values list. Also, by creating a new list in collectValues(), the other list is not affected ( it is entirely independent).

Related

While loop, how do I condition for when input equals nothing?

Create a program that will keep track of items for a shopping list. The program should keep asking for new items until nothing is entered (no input followed by enter key). The program should then display the full shopping list
How do I write the condition so it works?
The code I'm writing looks like this:
x = []
i = 0
while i != '':
x.append(input('what u want?'))
i = i + 1
print(x)
```
`
Hitting Enter only on input() returns an empty string. Values such as empty containers, zero-length strings, or numerically equivalent to zero are considered false in conditional statements.
Python >= 3.8 (supports := operator):
items = []
while item := input('Item? '):
items.append(item)
print(items)
Python < 3.8:
items = []
while True:
item = input('Item? ')
if not item: break
items.append(item)
print(items)
Demo:
Item? one
Item? two
Item? three
Item?
['one', 'two', 'three']
Find len of user input & check with if accordingly
x = []
while 1:
ask= input('what u want?')
if len(ask)>0:
x.append(ask)
else:
print("Good bye")
break
print(x)
output #
what u want?rice
what u want?sugar
what u want?
Good bye
['rice', 'sugar']
Code correction
It is not ideal to choose hit enter to exit the loop. You need to assign keyword to make sure user really wants to exit.
x = []
while 1:
ask= input('what u want?')
if len(ask)>0 and ask !="finish":
x.append(ask)
else:
print("Good bye")
break
print(x)
With this user will have clarity when to checkout.
More interactive way:
x = []
while 1:
ask= input('what u want?')
if len(ask)>0 and ask !="finish":
x.append(ask)
else:
confirmation = input('Do you really want to exit? - yes or no')
if confirmation =="yes":
print("Good bye")
break
else:
print("Let's continue shopping")
pass
print(x)

How can I convert the sum of my list to an Integer in Python 3? [duplicate]

This question already has answers here:
How can I read inputs as numbers?
(10 answers)
Closed 8 months ago.
I don't understand why the code is causing errors. For example, the error says that you can't add an integer and a string together, but I've already converted the string to an Integer. Could you help me fix it? The code is attached. Thanks.
# In this program I will collect data
# values from the user and use python built-in functions
# to display various info about the data set
# Giving user directions
print("In this programme, you can enter")
print("some numbers and it will display the")
print("minimum, maximum, range and average")
print("of the data set you entered.")
# Setup
list = []
loop = True
# Creating function for process of entering number
def enterNumber():
print()
x = input("Enter an integer: ")
y = str.isdigit(x)
if y == True:
list.append(x)
print()
print("Successfully added to list")
print()
print("Here is your list so far")
print(list)
elif y == False:
print()
print("Sorry, this is not an integer")
else:
print("Error. Kill and start again")
while loop == True:
enterNumber()
print()
print("Would you like to add another value?")
print()
a = input("Enter 1 for Yes, enter 0 for No: ")
if a == "0":
loop = False
print()
print()
print("------------------------------------------------")
print()
print("Count:", len(list))
print()
print("Minimum:", min(list))
print()
print("Maximum:", max(list))
print()
print("Range:", int(max(list)) - int(min(list)))
print()
print("Average:", int(sum(list)) / int(len(list)))
It seems like this last line is the problem.
You need to use int() function after checking if y value is True. If not you will be appending an string value always to your list:
def enterNumber():
print()
x = input("Enter an integer: ")
y = str.isdigit(x)
if y == True:
list.append(int(x)) #int(x) converts x to integer
...
The reason for the issue is that you have string values in your list, which doesn't work.
Simple test:
l = ['1', '2']
sum(l)
results in the same error.
Easiest fix is mentioned by Cardstdani.
You have not asked for it. But there is a serious issue in your code:
You should avoid at all cost to name your list list as this overwrites the built-in list() function.
# In this program I will collect data
# values from the user and use python built-in functions
# to display various info about the data set
# Giving user directions
print("In this programme, you can enter")
print("some numbers and it will display the")
print("minimum, maximum, range and average")
print("of the data set you entered.")
# Setup
list1 = []
loop = True
# Creating function for process of entering number
def enterNumber():
print()
x = input("Enter an integer: ")
y = str.isdigit(x)
if y == True:
list1.append(x)
print()
print("Successfully added to list")
print()
print("Here is your list so far")
print(list)
elif y == False:
print()
print("Sorry, this is not an integer")
else:
print("Error. Kill and start again")
while loop == True:
enterNumber()
print()
print("Would you like to add another value?")
print()
a = input("Enter 1 for Yes, enter 0 for No: ")
if a == "0":
loop = False
print()
print()
print("------------------------------------------------")
print()
print("Count:", len(list1))
print()
print("Minimum:", min(list1))
print()
print("Maximum:", max(list1))
print()
print("Range:", int(max(list1)) - int(min(list1)))
print()
list1 = list(map(int, list1))
print("Average:", sum(list1) / len(list1))

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)

changing data from printing line by line to a list (in a text file)

I'm using python, idle version 3.4.2
My code when it prints, print 3 scores per name but they print like this:
Maya: 3
Maya:2
Maya: 4
I was wondering if there was any way to get it to print like this in a list/dictionary so i can call upon the scores later for sorting
Maya = [3,2,4]
Here is my code.
students_names = []
import random #import module
print("What is your name?") #prints writing in brackets
name = input().title() #Capitalizes the first letter of the word inputted
students_names.append(name)
print("What class are you in? (Enter 1, 2 or 3)") #asks the user to input a number
while True:
try:
class_number = int(input()) #asks for an integer input from user
except ValueError:
print("Sorry, I didn't understand that, please try again") #print statement
continue
if class_number > 3: #if input is more than 3
print("SORRY but that class isn't recognised, try again") #print statement
continue
else:
print ("Hello,", name, "from class", class_number, "welcome to my quiz") #prints writing in brackets and anything saved in the variable "name" and "class_number"
break #break out of loop
score = 0 #sets the variable "score" to zero
question = 0 # sets the variable "question" to zero
print(class_number)
while question < 3:#If questions (intitally set to 0) is smaller than 10, carry out this function
question +=1 # add one to the value of "question"
maths = random.randint(1,3) #randomly generate a number from 1-3 and store as "maths"
num1 = random.randint(1,10)#randomly generate an integer from 1-10 and store as "num1"
num2 = random.randint(1,10)#randomly generate a second integer from 1-10 and store as "num2"
if maths == 1: #if the number generated is 1
print(num1, "+", num2) #prints num1 + num2
ans = num1 + num2 #sets "ans" to equal the value of num1 added to num2
elif maths == 2: #if the number generated is 1
print(num1, "*", num2) #print num1 multiplied by num2
ans = num1 * num2 #sets "ans" to equal the value of num1 multiplied by num2
else: #else run this part of code
print(num1, "-", num2) #print num1 subtracted by num2
ans = num1 - num2 #sets "ans" to equal the value of num1 subtracted by num2
while True:
try:
user_ans = int(input()) #user inputs answer to question
except ValueError: #runs when the user input is no an integer
print ("SORRY but that answer isn't recognised, try again")
else:
break
if user_ans == ans:
score+=1
print("Well done, you are CORRECT")
else:
print("SORRY, you are INCORRECT") #print writing in brackets
print("The correct answer was", ans)
if score == 10: #run this part of code if "score" equals 10
print("fantastic", name, "you got full marks!")#print statement and name
elif score >= 6: #run this part of code if "score" is larger than or equal to 6
print("well done, there's some improvement to be done here though", name, "you got", score, "/10")# then print statement and score
elif score <=5: #run this part of code if "score" is smaller than or equal to 5
print("hmm, maybe some more practise would be beneficial", name, "you got", score, "/10") #then print statement and score
class_number = str(class_number) + ".txt" #this adds '.txt' to the end of the file (therefore creating a text file) so it can be used to create a file under the name of the class
file = open(class_number, 'a') #opens the file in 'append' mode so you don't delete all the information
file.write(str(students_names))
file.write(str(name + " : ")) #writes the name and ":" to file
file.write(str(score)) #writes the score to file
file.write('\n')#writes the score to the file
file.close()#safely closes the file to save the information
Sure simply add the score values foreach person to a new dictionary.
name_dict = {}
if name in name_dict:
name_dict[name].append(new_score)
else:
name_dict[name] = [new_score]
It is a little bit hard to follow up on your code. Therefore I was not completely able to integrate it.
Ok, I think I get what you're looking for. But to simplify my answer to that, we first need to simplify your example. A good way to do so, is to cut your code into functions:
How to store your results?
First we'll look at where you need help on, which is the last bit of your code, which fits in a function we'll call store_results():
def store_results(...):
class_number = str(class_number) + ".txt" # this adds '.txt' to the end of the file (therefore creating a text file) so it can be used to create a file under the name of the class
file = open(class_number, 'a') # opens the file in 'append' mode so you don't delete all the information
file.write(str(students_names))
file.write(str(name + " : ")) # writes the name and ":" to file
file.write(str(score)) # writes the score to file
file.write('\n') # writes the score to the file
file.close() # safely closes the file to save the information
I used here ... for the arguments of the function, which is not python, to have a thought about it. What arguments does that function needs to work as is?
class_number: the class the student answering the QA is in
name: the score the student had on the QA
student_names
What you're doing here, is that when you run that code, you're appending name
into student_names, which will always contain one, and only one name. So when
you write file.write(str(students_names)), for a user whose name is John, you'll
end up writing:
...
['John']
John : 5
...
Which is not something I believe you're expecting. You actually do not need that list at all.
So as a first update, you should do:
def store_results(class_number, name, score):
class_file = "{}.txt".format(class_number) # this adds '.txt' to the end of the file (therefore creating a text file) so it can be used to create a file under the name of the class
with open(class_file, 'a') as f: # opens the file in 'append' mode so you don't delete all the information
f.write("{}: {}\n".format(name, score) # outputs the user's score to the file
Other changes in that snippet are:
- you shall not use file as a variable as it already exists as a global type, and using it in
your code is considered bad practice called "shadowing" which can lead to hard to find bugs
(not in this case, but if you don't take the good habits now, it's bite you in a future code).
- you shall use with open() as f: construct instead of opening and closing the file manually,
because in your existing code, if there's an exception thrown between open and close your
file won't be properly closed, ending up in possible lost writes.
- you shall use format strings instead of direct string concatenation, which makes the code
easier to read and to modify.
Now, that being said, you'll still have your issue having the result of each test taken
by an user being shown as:
John: 2
John: 4
John: 5
The right way to solve this is to not use "blinded" appending to the file, but instead
use the file as some sort of very basic database. The most simple option would be to
write your scores within a JSON file, which is syntactically compatible with python
(pretty useful for manual testing):
import os
import json
def store_results(class_number, name, score):
# this adds '.json' to the end of the file (therefore creating a json file)
class_file = "{}.json".format(class_number)
# first step: load the existing data
# first test if the file exists, and if not, use an empty score dictionary
if not os.path.exists(class_file):
scores = {}
# otherwise populate the dictionary
else:
# open as read only, because we just want the data out of it
with open(class_file, 'r') as f:
# load contents of the json file "f" as object "scores"
scores = json.load(f)
# second step: update the data
scores.setdefault(name, []).append(score)
# third step: update the file
# use 'w' when opening the file to overwrite all data within it
with open(class_file, 'w') as f:
# dump object "scores" within file "f"
json.dump(scores, f)
Within this code, I used a trick to do insertion of the score in one line:
scores.setdefault(name, []).append(score)
which is equivalent to:
# if the user's "name" is not already in the dictionary
if name not in scores.keys():
# add it as a new key containing an empty list
scores[name] = []
# append the "score" to the list indexed by the user's "name"
scores[name].append(score)
Then the results within a file would look like:
{"John":[3,5,10],"Jane":[2],"Bob":[1,0,2]}
To make the output file more readable you can change the json.dump line into:
json.dump(scores, f, sort_keys=True, indent=4, separators=(',', ': '))
which will output:
{
"Bob": [
1,
0,
2
],
"Jane": [
2
],
"John": [
3,
5,
10
]
}
How to run the QA?
Finally you want to create another function that handles the QA process, within which
you call the function we just defined
# add the following import at the start of your script if you're running python2 and not python3
from __future__ import print_function
def run_qa():
print("What is your name?") # prints writing in brackets
name = input().title() # Capitalizes the first letter of the word inputted
print("What class are you in? (Enter 1, 2 or 3)") # asks the user to input a number
while True:
try:
class_number = int(input()) # asks for an integer input from user
except ValueError:
print("Sorry, I didn't understand that, please try again") # print statement
continue
if class_number > 3: # if input is more than 3
print("SORRY but that class isn't recognised, try again") # print statement
continue
else:
break # break out of loop
# prints writing in brackets and anything saved in the variables "name" and "class_number"
print ("Hello, {} from class {} welcome to my quiz".format(name, class_number))
score = 0 # sets the variable "score" to zero
question = 0 # sets the variable "question" to zero
while question < 3: # If questions (initially set to 0) is smaller than 10, carry out this function
question += 1 # add one to the value of "question"
maths = random.randint(1,3) # randomly generate a number from 1-3 and store as "maths"
num1 = random.randint(1,10) # randomly generate an integer from 1-10 and store as "num1"
num2 = random.randint(1,10) # randomly generate a second integer from 1-10 and store as "num2"
if maths == 1: # if the number generated is 1
print("{} + {} = ?".format(num1, num2)) # prints num1 + num2
ans = num1 + num2 # sets "ans" to equal the value of num1 added to num2
elif maths == 2: # if the number generated is 1
print("{} * {} = ?".format(num1, num2)) # print num1 multiplied by num2
ans = num1 * num2 # sets "ans" to equal the value of num1 multiplied by num2
else: # else run this part of code
print("{} - {} = ?".format(num1, num2)) # print num1 subtracted by num2
ans = num1 - num2 # sets "ans" to equal the value of num1 subtracted by num2
while True:
try:
# print a nice little prompt for the user to enter his answer
print("> ", end="")
user_ans = int(input()) # user inputs answer to question
# if an exception is raised by "int()" the break is not being called
# here you achieve the same as a single line, as you're doing in two
# lines with your try/except/else clause, making your code more readable.
break
except ValueError: # runs when the user input is no an integer
print ("SORRY but that answer isn't recognised, try again")
if user_ans == ans:
score += 1
print("Well done, you are CORRECT")
else:
print("SORRY, you are INCORRECT") # print writing in brackets
print("The correct answer was {}".format(ans))
if score == 10: # run this part of code if "score" equals 10
print("Fantastic {}, you got full marks!".format(name))# print statement and name
elif score >= 6: # run this part of code if "score" is larger than or equal to 6
print("Well done, there's some improvement to be done here, though {} you got {}/10".format(name, score))# then print statement and score
elif score <=5: # run this part of code if "score" is smaller than or equal to 5
print("hmm, maybe some more practice would be beneficial, {}, you got {}/10".format(name, score)) # then print statement and score
# return the results
return class_number, name, score
Finally, to call your code, you just need to add the following at the end of your script:
if __name__ == "__main__":
class_number, name, score = run_qa()
store_results(class_number, name, score):
the reason for the if statement is to make it possible to later include your code as
a module in another module without running it, which is considered good practice!
as another improvement I'd avoid repeating the same code several times to check input
from the user, but use a function instead:
def get_integer_input(maxval=None):
while True:
try:
# print a nice prompt
print("> ", eol="")
i = int(input()) # asks for an integer input from user
if maxval:
if i >= maxval:
continue
print("Sorry, input shall be inferior than {}, try again".format(maxval))
break
except ValueError:
print("Sorry, I didn't understand that, please try again") # print statement
return i
Then in your code you use it that way:
...
class_number = get_integer_input(maxval=3)
...
BTW, as an improvement, I'd actually split the run_qa in two functions: one that
generates the questions, and the other that does the interactive process.
so that you would do:
if __name__ == "__main__":
questions = generate_qa()
class_number, name, score = run_qa(questions)
store_results(class_number, name, score)
with generate_qa() being something like:
def generate_qa():
questions = []
while len(questions) < 3: # add a question until we have three generated
op = random.randint(0,2) # randomly generate a number from 1-3 and store as "maths"
num1 = random.randint(1,10) # randomly generate an integer from 1-10 and store as "num1"
num2 = random.randint(1,10) # randomly generate a second integer from 1-10 and store as "num2"
questions.append( (op, num1, num2) )
return questions
and then:
def run_qa(questions):
print("What is your name?") # prints writing in brackets
name = input().title() # Capitalizes the first letter of the word inputted
print("What class are you in? (Enter 1, 2 or 3)") # asks the user to input a number
class_number = get_integer_input(maxval=3)
# prints writing in brackets and anything saved in the variables "name" and "class_number"
print ("Hello, {} from class {} welcome to my quiz".format(name, class_number))
score = 0 # sets the variable "score" to zero
for op, left, right in questions:
if op == 0: # if the number generated is 0
op("{} + {} = ?".format(left, right)) # prints 'left' + 'right'
ans = left + right # sets "ans" to equal the value of num1 added to 'right'
elif op == 1: # if the number generated is 1
print("{} * {} = ?".format(left, right)) # print 'left' multiplied by 'right'
ans = left * right # sets "ans" to equal the value of num1 multiplied by 'right'
else: # the only possible value is: op == 2
print("{} - {} = ?".format(left, right)) # print 'left' subtracted by 'right'
ans = left - right # sets "ans" to equal the value of num1 subtracted by 'right'
user_ans = get_integer_input()
if user_ans == ans:
score += 1
print("Well done, you are CORRECT")
else:
print("SORRY, you are INCORRECT") # print writing in brackets
print("The correct answer was {}".format(ans))
if score == 10: # run this part of code if "score" equals 10
print("Fantastic {}, you got full marks!".format(name))# print statement and name
elif score >= 6: # run this part of code if "score" is larger than or equal to 6
print("Well done, there's some improvement to be done here, though {} you got {}/10".format(name, score))# then print statement and score
elif score <=5: # run this part of code if "score" is smaller than or equal to 5
print("hmm, maybe some more practise would be beneficial, {}, you got {}/10".format(name, score)) # then print statement and score
return class_number, name, score
Finally, a last improvement that could be done to your code is to use a dict containing the operators:
import operator
operations = {
'+': operator.add,
'*': operator.mul,
'-': operator.sub
}
and then you'd simplify run_qa as follows:
def run_qa(questions):
print("What is your name?") # prints writing in brackets
name = input().title() # Capitalizes the first letter of the word inputted
print("What class are you in? (Enter 1, 2 or 3)") # asks the user to input a number
class_number = get_integer_input(maxval=3)
# prints writing in brackets and anything saved in the variables "name" and "class_number"
print ("Hello, {} from class {} welcome to my quiz".format(name, class_number))
score = 0 # sets the variable "score" to zero
for op, left, right in questions:
# convert from index value into symbol (the "list()" is a needed trick for python3
op = list(operations.keys())[op]
print("{} {} {} = ?".format(left, op, right))
# calculate the operation with operator 'op' using 'left' and 'right'
ans = operations[op](left, right)
user_ans = get_integer_input()
if user_ans == ans:
score += 1
print("Well done, you are CORRECT")
else:
print("SORRY, you are INCORRECT") # print writing in brackets
print("The correct answer was {}".format(ans))
if score == 10: # run this part of code if "score" equals 10
print("Fantastic {}, you got full marks!".format(name))# print statement and name
elif score >= 6: # run this part of code if "score" is larger than or equal to 6
print("Well done, there's some improvement to be done here, though {} you got {}/10".format(name, score))# then print statement and score
elif score <=5: # run this part of code if "score" is smaller than or equal to 5
print("hmm, maybe some more practice would be beneficial, {}, you got {}/10".format(name, score)) # then print statement and score
return class_number, name, score
Nota Bene: I have not tested my code locally, it's been live coding within the answer box
of stackoverflow, so there might be syntax errors and maybe minor bugs. The goal of
my answer is to emphasize what you're doing wrong and show you how to do better. So,
please do not take it "as is" to copy/paste, but read it through, understand what I'm
showing to you, and update your code with what I given you as an improvement.
Here's a full example I just tested:
# make the script both py2 and py3 compatible
from __future__ import print_function
import sys
if sys.version_info.major == 2:
input = raw_input
import operator
import random
import json
import os
def store_results(class_number, name, score):
# this adds '.json' to the end of the file (therefore creating a json file)
class_file = "{}.json".format(class_number)
# first step: load the existing data
# first test if the file exists, and if not, use an empty score dictionary
if not os.path.exists(class_file):
scores = {}
# otherwise populate the dictionary
else:
# open as read only, because we just want the data out of it
with open(class_file, 'r') as f:
# load contents of the json file "f" as object "scores"
scores = json.load(f)
# second step: update the data
scores.setdefault(name, []).append(score)
# third step: update the file
# use 'w' when opening the file to overwrite all data within it
with open(class_file, 'w') as f:
# dump object "scores" within file "f"
json.dump(scores, f, sort_keys=True, indent=4, separators=(',', ': '))
def get_integer_input(maxval=None):
while True:
try:
# print a nice prompt
print("> ", end="")
i = int(input()) # asks for an integer input from user
if maxval:
if i >= maxval:
continue
print("Sorry, input shall be inferior than {}, try again".format(maxval))
break
except ValueError:
print("Sorry, I didn't understand that, please try again") # print statement
return i
operations = {
'+': operator.add,
'*': operator.mul,
'-': operator.sub
}
def generate_qa():
questions = []
while len(questions) < 3: # add a question until we have three generated
op = random.randint(0,2) # randomly generate a number from 1-3 and store as "maths"
num1 = random.randint(1,10) # randomly generate an integer from 1-10 and store as "num1"
num2 = random.randint(1,10) # randomly generate a second integer from 1-10 and store as "num2"
questions.append( (op, num1, num2) )
return questions
def run_qa(questions):
print("What is your name?") # prints writing in brackets
name = input().title() # Capitalizes the first letter of the word inputted
print("What class are you in? (Enter 1, 2 or 3)") # asks the user to input a number
class_number = get_integer_input(maxval=3)
# prints writing in brackets and anything saved in the variables "name" and "class_number"
print ("Hello, {} from class {} welcome to my quiz".format(name, class_number))
score = 0 # sets the variable "score" to zero
for op, left, right in questions:
# convert from index value into symbol (the "list()" is a needed trick for python3
op = list(operations.keys())[op]
print("{} {} {} = ?".format(left, op, right))
# calculate the operation with operator 'op' using 'left' and 'right'
ans = operations[op](left, right)
user_ans = get_integer_input()
if user_ans == ans:
score += 1
print("Well done, you are CORRECT")
else:
print("SORRY, you are INCORRECT") # print writing in brackets
print("The correct answer was {}".format(ans))
if score == 10: # run this part of code if "score" equals 10
print("Fantastic {}, you got full marks!".format(name))# print statement and name
elif score >= 6: # run this part of code if "score" is larger than or equal to 6
print("Well done, there's some improvement to be done here, though {} you got {}/10".format(name, score))# then print statement and score
elif score <=5: # run this part of code if "score" is smaller than or equal to 5
print("hmm, maybe some more practise would be beneficial, {}, you got {}/10".format(name, score)) # then print statement and score
return class_number, name, score
if __name__ == "__main__":
questions = generate_qa()
class_number, name, score = run_qa(questions)
store_results(class_number, name, score)
HTH

Loop keeps going after being carried out

def Help(string):
while True:
if string == 'Manifest':
return Manifest()
break
elif string == 'Intent':
return Intent()
break
else:
print('The options available are: \n')
for i in andHelp:
print(i)
print('Type Q to Quit \n')
x = input('What option do you choose: ')
print('\n')
if x == 'Q':
break
else:
Help(x)
How come if it goes into the else statement it will keep looping?
for example:
"The options available are:
Intent
Manifest
Type Q to Quit
What option do you choose: " <-- this will keep coming up aswell as the function I choose.
You don't even need a while loop for what you are checking. Use this instead:
def Help(string):
if string == 'Manifest':
return Manifest()
elif string == 'Intent':
return Intent()
else:
print('The options available are:\n%s\nType Q to Quit\n' % '\n'.join(andHelp))
x = input('What option do you choose: ')
print('\n')
if x != 'Q':
Help(x)
note: I modified your prints a bit to reduce extra lines that really, didn't need to be there.
note2: As you may see in the comments, it may be dangerous to do this recursively without a limitation because you may reach a maximum depth level.
Your actual problem is due to your recursion not actually returning the inner frame's value, but eliminating the recursion seems a more straightforward solution.
What's goofy about this is doing a recursion inside a loop. Both the recursion and the loop serve the same purpose: To make the option choice keep happening until a valid option is given. So you can definitely eliminate one:
def Help(string):
while True:
if string == 'Manifest':
return Manifest()
break
elif string == 'Intent':
return Intent()
break
else:
print('The options available are: \n')
for i in andHelp:
print(i)
print('Type Q to Quit \n')
string = input('What option do you choose: ') # Change `x` to `string` so next iteration will change behavior
print('\n')
if string == 'Q':
break
As Inbar Rose's answer points out, you can shorten this quite a bit with recursion, but since Python requires a recursion limit, you can make the program crash by forcing it to recur beyond that limit. So perhaps sticking with the loop is better. Anyway, you can clean it up further by having the validation of string be the condition of the loop itself:
def Help(string):
validOptions = ('Manifest', 'Intent', 'Q')
while string not in validOptions:
print('The options available are: \n')
for i in andHelp:
print(i)
print('Type Q to Quit \n')
string = input('What option do you choose: ')
print('\n')
# Now you have a guaranteed-valid string, so you don't need this part in the loop.
if string == 'Manifest':
return Manifest() # No need for a 'break' after a return. It's [dead code](http://en.wikipedia.org/wiki/Dead_code)
elif string == 'Intent':
return Intent()
elif string == 'Q':
return

Categories

Resources