Issues with lists? Error checking not working - python

I am relatively new to python, and I just started learning how to use classes. This is the first program I've made where I've tried to integrate them, but I'm coming up with a small issue I can't seem to fix, and I think it has to do with lists. The code is as follows:
(The topic is getting the user to choose what type of seat to purchase).
class SeatBooking:
def __init__(self, seat):
self.seat = seat
possible_types = []
possible_types.extend(["Low_Economy", "Standard_Economy", "High_Economy",
"Business", "First", "Residence"])
possible_types = " ".join(possible_types)
while True:
if self.seat not in possible_types:
print("Sorry, but this is not a valid answer. Please try again!")
self.seat = str(input("What type of ticket would you like? The possible types are: {} "
.format(possible_types)))
else:
print("You have chosen to book a {} ticket.".format(self.seat))
confirmation = str(input("Please confirm with 'Yes' or 'No': ")).lower()
if confirmation == "yes":
print("Excellent decision! Ready to continue")
print("=" * 170)
break
elif confirmation == "no":
self.seat = str(input("What type of ticket would you like? The possible types are: {} "
.format(possible_types)))
else:
print("That doesn't seem to be a valid answer.")
Here is the main file (to execute the different classes I'll make):
import type_seat
# Choose the seat to book
print("=" * 170)
print("Welcome to Etihad! This program can help you organize your flight, payments and usage of miles!")
possible_types = []
possible_types.extend(["Low_Economy", "Standard_Economy", "High_Economy",
"Business", "First", "Residence"])
possible_types = " ".join(possible_types)
seat_type = str(input("What type of ticket would you like? The possible types are: {}. "
.format(possible_types)))
type_seat.SeatBooking(seat_type)
The problem I have is that I seem to be able to enter certain letters and it doesn't count them as an error even though they're not one of the available seats. For example, when I enter the letters "h" or "s", my error checking part of the code doesn't respond to it, but when I enter the letter "b" or random words like "try" it does. It doesn't seem to be completely random though, and it seems to only happen with letters or parts of the first 3 'items' in the possible_types[] list. However, I haven't tested this fully. This is why I thought it had something to do with lists, so if anyone knows what's causing this, I'd really appreciate it if they could help me resolve this and perhaps help me from repeating this mistake in the future!
Note, for the lists I am using .join, but I also tried str().

You don't have a list, you are testing characters against one long string:
possible_types = " ".join(possible_types)
The letters h and s are in that string (in the words High_Economy and Business, respectively), but the sequence try doesn't appear anywhere in the string.
If you only wanted to allow whole words to match, you'd need to leave possbile_types a list, or ideally convert it to a set (as sets allow for fast membership testing). You can define the list, no need for list.extend() here:
possible_types = ["Low_Economy", "Standard_Economy", "High_Economy",
"Business", "First", "Residence"]
or make it a set by using {...}:
possible_types = {"Low_Economy", "Standard_Economy", "High_Economy",
"Business", "First", "Residence"}
Do not join this into a string, just test directly against the object:
if self.seat not in possible_types:
If you still need to show the values to a user in an error message, join the values then, or store the str.join() result in a different variable for that purpose.
Note that you shouldn't deal with user input validation in the class __init__ method. Leave user interaction to a separate piece of code, and create instances of your class after you validated. That way you can easily swap out user interfaces without having to adjust all your data objects too.

possible_types = " ".join(possible_types)
Above statement will create one string as "Low_Economy Standard_Economy High_Economy Business First Residence".
Now you are doing
if self.seat not in possible_types:
This will check for a particular character in the string present or not. In your case you are finding 'h' which is present and 'try' which isn't.
Your program will work if you remove this statement
possible_types = " ".join(possible_types)

Related

Need to set a default value for multiple input for list in Python

I'm trying to get the default value if input is blank, how can I do that?
Output what I'm getting is for variable is blank if there is no user input.
Brand_default = 'ABC','XYZ'
cate_default = 'GKK','KKL','MKK','UKK'
Brand = list(input('Please enter Brand? (ABC/XYZ)= ').split(',') or Brand_default)
Cate = list(input('Please enter Category?GKK,KKL,MKK,UKK = ').split(',') or cate_default)
Your logic needs to decide whether the value is empty, and then split if not. Unfortunately, this means your otherwise rather elegant or formulation won't work.
def split_or_default(prompt, default):
response = input(prompt + " (" + "/".join(default) + ") ")
if response == "":
return default
return response.split(",")
Brand = split_or_default(
'Please enter Brand?',
['ABC','XYZ'])
Cate = split_or_default(
'Please enter Category?',
['GKK','KKL','MKK','UKK'])
Notice also how the defaults are also lists now. I suppose your code could work with lists or tuples, but that seems like an unwelcome complication.
Tangentially, you should probably remove the "Please enter" part from the prompt. It's nice to be polite, but in user interfaces, it's actually more friendly to be concise.
Requiring commas between the values is also somewhat cumbersome. If some values could contain spaces, you need for the input to be unambiguous; but if these examples are representative, you could just as well split on whitespace.
In keeping with the DRY Principle I refactored the repeated code into a function.

Trying to Build a Sandwich Making Simulator

First time using Stackoverflow.
I'm a total noob with Python so I need a little help. I'm trying to make a choice based text adventure game and in the middle of it is going to be a sandwich making simulator (don't ask how my mind works) and I need a little help.
def sandwich():
print("You see bread, meat, cheese and mayo.")
while True:
try:
print(" 1. Bread \n 2. Meat \n 3. Cheese \n 4. Mayo")
print ("Select the ingredients based on number. Which would you like to grab?")
response = set(int(input("Select ingredients: ").strip))
except ValueError:
print("Please enter an integer!")
I only have four choices to keep it simple so I can build from there. Basically I want to make the program check for user integer input and depending on that input give feedback on the sandwich that's created.
for example:
if response == "1234":
print("Wow that's an amazing sandwich")
But I want the program to be able to be smart enough to do this regardless of the order that is given. So if someone puts in "4321" instead of "1234", it can give the same result. Currently I'm using set, int, and strip on line 7 (not sure if that's good or not) so that there can't be duplicates, and if spaces is added it should strip it away. It should also give an error if an integer is not entered.
I'm thinking of using for loops with in, but I have no idea where to begin or if that's even the right path.
Any points in the right direction would be appreciated!
Is better to put the list of ingredients in a dictionary, so you can easily add or substract ingredients, and you have a relation between the number and the ingredient.
Strip is a function call, so it has to be written .strip()
Is better to not add the response directly to the set of ingredients, because you should validate it first.
You need a way to stop adding ingredients. If the user does not writes an integer, you could ask if he wants to stop adding ingredients.
sandwichIngredients = {1: "Bread", 2: "Meat", 3: "Cheese", 4: "Mayo"}
def sandwich():
chosenIngredients=set()
print("You see "+ ", ".join(sandwichIngredients.values())+".")
while True:
try:
print(*[f"{number}. {ingredient}" for number, ingredient in sandwichIngredients.items()], sep="\n")
print ("Select the ingredients based on number. Which would you like to grab?")
response=int(input("Select ingredients: ").strip()) #strip is a function call, so it has to be written .strip()
if response in chosenIngredients:
print("You already have that ingredient.")
continue
elif response not in sandwichIngredients:
print("That is not an ingredient.")
continue
else:
chosenIngredients.add(response)
if len(chosenIngredients)==len(sandwichIngredients):
print("Wow that's an amazing sandwich.")
break
except ValueError:
if input("That is not a number. Do you want to finish the sandwich? (y/n)").lower()=="y":
break
print("Please enter an integer!")
#now you can print the ingredient names by using the dictionary
print("your sandwich has the following ingredients: " + ", ".join([sandwichIngredients[i] for i in chosenIngredients]))
sandwich()

Why am I receiving "incorrect" output in this ifelse statement?

I am new to python and trying to learn by doing small projects.
I am trying to write a program that displays the names of the four properties and
asks the user to identify the property that is not a railroad. The user should be informed if the selection is correct or not.
properties = "Reading,","Pennsylvania","B & O","Short Line"
question = str(input("Which is not a railroad?")) **Short Line**
if properties == "Short Line":
print("correct")
else:
print("incorrect")
However, my final output shows as "incorrect", what am i doing wrong?
The four railroad properties
are Reading, Pennsylvania,
B & O, and Short Line.
Which is not a railroad? Short Line
Correct.
Short Line is a bus company.
Couple things I see with this code you have posted.
First, not sure if you actually have **Short Line** in your actual code but if you are trying to comment use # That way it won't be interpreted at run time.
Second as mentioned in other answers you are checking against properties which is pulling in your array. You should be checking against your input which is stored at question.
properties = "Reading,","Pennsylvania","B & O","Short Line"
question = str(input("Which is not a railroad?")) # **Short Line**
if question == "Short Line": # replaced properties with question
print("correct")
else:
print("incorrect")
print(properties)
print(question)
I find that when I am having troubles understanding why something is not working I throw some print statements in to see what the variables are doing.
You may want to catch the user in a loop, otherwise you would have to constantly have to run the code to find the correct answer(unless that is the desired behavior, then you can leave it as you have it). Also, be aware that you may want to uppercase or lowercase because a user may provide the answer as "Short line" (lower case "L"), and the code will return as incorrect. Of course, that depends on what you will accept as an answer.
Sample
print ("Reading,Pennsylvania,B & O, or Short Line. Which is not a railroad?")
user_input = input("Please provide an answer: ")
# != the loop will close once the user inputs short line in any form
# The upper.() will convert a user_input string to all caps
while user_input.upper() != "SHORT LINE":
print ("Incorrect, Please try again.")
user_input = input("Which one is not a railroad? ")
print ("Correct")
Prettied it up for you
print( "Reading, Pennsylvania, B & O, and Short Line. Which is not a railroad?" )
print("Which is not a railroad?")
answer = input()
if answer == "Short Line":
print("correct")
else:
print("incorrect")

How to choose the word in the dictionary menu?

I am writing a English dictionary using python 2. I created a dictionary. for example, "home" and "horse" in the dictionary's key. If the user types "ho", "home" and "horse" will come. I put these in the bottom line. But when the user selects word 1, I want to call the key and value in the dictionary that I set first. How can I do it?
myEngDict = {"horse": "The horse (Equus ferus caballus) is one of two extant subspecies of Equus ferus","home": "the place where one lives permanently, especially as a member of a family or household."}
def Words():
word_List = []
count = 0
search_words = raw_input("Please enter a search term: ")
for i in myEngDict.keys():
if i.startswith(search_words):
count+=1
word_List.append(i)
print "{}{}{}".format(count,".", i)
else:
pass
choose = input("Which one?")
For example, if "home" comes out first, user choose 1:
Program display:
home: the place where one lives permanently, especially as a member of a family or household.
First, you should use raw_input in that final line. Then you need to look up the provided in the word_List.
while True:
try:
choose = int(raw_input("Which one?"))
# Keep the key as a separate variable for faster reference
key = word_List[choose - 1]
# Use labels with the format function. It's easier to read and understand
print '{label}: {text}'.format(label=key, text=myEngDict[key])
# Be sure to have a break or return on success.
return
except ValueError:
# If someone provides 'cat', it will raise an error.
# Inform the user and go back to the start.
print 'Please provide an integer'
except IndexError:
# The user has provided a value above the length of word_List or
# less than one. Again, inform the user and go back to start.
print 'You must enter a number between 1 and {c}'.format(c=len(word_List))
By not changing to much your code, you can just add a print statement after choose in your function at the same identation:
print ("%s : %s"%(word_List[choose-1], myEngDict[word_List[choose-1]]))

Python 3.6.2 loop not working like I wanted it too

I am currently writing a code for my GCSE coursework and I am kind of stuck with my for loop which also contains an if-else statement.
I have done a code similar to this earlier in the program and it works perfectly fine but for some reason this part doesn't and I was wondering if someone could help me.
What I am trying to do is make a quiz type program and the part that I need help with is choosing the subject that the user wants to do.
The user has to type in their preferred subject but if they type the subject in wrong, or type in something invalid, then the program should allow the user to type it in again.
So far, if you type in a subject correctly the first time, the program will proceed to the next stage.
However, if you type it incorrectly the first time, it will ask the user to try again. But if you type it in correctly the second time, it will again ask the user to try again. Instead of having the program make the user type the subject again, even though it should've been valid the when they typed it in correctly, I want the program to proceed to the next stage.
Available subjects:
subjects = []
algebra = ("algebra")
computing = ("computing")
subjects.append(algebra)
subjects.append(computing)
Part that I need help with:
with open("student_file.csv", "a+") as studentfile:
studentfileReader = csv.reader(studentfile, delimiter = ',')
studentfileWriter = csv.writer(studentfile, delimiter = ',')
print("Available subjects:\n-Algebra\n-Computing\n")
ChosenSubject = input("What subject would you like to do? ")
ChosenSubject.lower()
for i in range(2):
if ChosenSubject in subjects:
print("\n")
break
else:
print("\nPlease try again.")
ChosenSubject == input("What subject would you like to do?")
ChosenSubject.lower()
if ChosenSubject in subjects:
print("working")
else:
print("You keep typing in something incorrect.\nPlease restart the program.")
In the else block, perhaps you'd want to replace the '==' with '='.
Also do you want to give the user just two tries or keep asking them until they answer correctly? (The latter is what I inferred from your question, for that I'd recommend using continue)
The for loop just iterates over a collection of objects. Consider a list my_list = ['a', 'b', 'c']. On each iteration over my_list using for loop, it fetches one of the elements in order without repetition. range(2) is equivalent to [0, 1].
Try this:
print("Available subjects:\n-Algebra\n-Computing\n")
for i in range(2):
# `i` is 0 on first iteration and 1 on second. We are not using `i` anywhere since all we want is to loop :)
chosen_subject = input("What subject would you like to do? ")
if chosen_subject.lower() in subjects:
print("\n")
break
if chosen_subject.lower() in subjects:
print("working")
else:
print("You keep typing in something incorrect.\nPlease restart the program.")
This is not an optimal solution, but since your learning I will try to keep it as close as your solution. Your problem is that calling ChosenSubject.lower() does not change the actual value in ChosenSubject.
Here is a working example:
print("Available subjects:\n-Algebra\n-Computing\n")
ChosenSubject = input("What subject would you like to do? ")
subjects = ["algebra", "computing"]
for i in range(2):
if ChosenSubject.lower() in subjects:
print("\n")
break
else:
print("\nPlease try again.")
ChosenSubject = input("What subject would you like to do?") #not '=='
if ChosenSubject.lower() in subjects:
print("working")
else:
print("You keep typing in something incorrect.\nPlease restart the program.")
This from the doc:
This method returns a copy of the string in which all case-based
characters have been lowercased.

Categories