Why doesn't the second part of this loop work? [closed] - python

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
The user should insert a name as an input and then confirm with a yes or no (or any of its derivatives) if the 3 worded name includes a middle name or not. So far, I've gotten the loop to work if the answer is yes; however it keeps looping the question if the answer is no.
The purpose: if the answer is yes, the program will understand its a 3 worded name with a middle name and therefore execute naming combinations with the middle name; if its no, the program will understand its a 3 worded name with a second last name instead of a middle name and therefore execute naming combinations accordingly.
Please note I have exluded a lot of the code for sharing purposes.
What I'm I doing wrong? My question is in regards to the elif part of the loop.
print ('enter name')
providedname = input ()
while providedname != 'quit':
if len(providedname.split())==4:
pass
elif len(providedname.split())==3:
print ('Does the name include a middle name or middle initial? Please type yes or no:')
userinput = input()
if userinput.startswith ('ye' or 'Ye' or 'YE' or 'ya' or 'Ya' or 'YA'):
firstname, middlename, lastname = providedname.split()
elif userinput.startswith ('no' or 'No' or 'NO' or 'na' or 'Na' or 'NA'):
firstname, lastname, secondlastname = providedname.split()
else:
pass
print ('enter name or type quit or q to exit')
providedname=input()
continue

You can't use or like that. It makes sense in English, but it doesn't work in Python. One way to express what you're doing is with a mini for loop along with the any function, like so:
if any(userinput.startswith(string) for string in ['ye', 'Ye', 'YE', 'ya', 'Ya', 'YA']):
It reads almost like English if you shuffle the word order around a bit:
If the user input starts with any of the strings in this list...
Even better is to lowercase the input string first. Then you don't have to check so many combinations.
userinput = input().casefold() # Python 3.3+
userinput = input().lower() # Earlier
if any(userinput.startswith(string) for string in ['ye', 'ya']):
As it happens, startswith can also accept a list of strings. You can actually ditch the all the any() machinery and have simply:
if userinput.startswith(('ye', 'ya')):
(Thanks to #kindall for that tip.)

So, just run this in the interpreter
>>> 'ye' or 'Ye' or 'YE' or 'ya' or 'Ya' or 'YA'
'ye'
Your startswith isn't working the way you think it does.
Other than that, you can shorten that statement up if you lowercase your strings.
Runnable example
while True:
providedname = input ('enter name or type quit or q to exit: ')
if providedname in {'quit', 'q'}:
break
names = providedname.split()
if len(names) == 4:
pass
elif len(names) == 3:
userinput = input('Does the name include a middle name or middle initial? Please type yes or no:')
if userinput[:2].lower() in {'ye', 'ya'}:
firstname, middlename, lastname = names
elif userinput[:2].lower() in {'no' , 'na'}:
firstname, lastname, secondlastname = names
else:
pass
print(firstname, lastname)

It LOOKS as though you're missing the ending ' on the print command inside your elif ('Does the name include....), causing the rest of it to be taken as more text input. Try adding that ' and see if that helps!

First, you could have more complex names, for example, "Oscar De La Hoya", which would skip because the name would have length = 4. Ignoring 'difficult names', the next thing would be to work on cleaning the user's input. I would clean the user's input like so:
userinput = input().lower().strip()
This way you can make is simpler for yourself and also more readable.
Now you can do:
if userinput == 'yes':
firstname, middlename, lastname = providedname.split()
else:
firstname, lastname, secondlastname = providedname.split()
Finally (as the other answer states), if a 'valid' input is given, you'll want to break out of the while loop with a break.

You have 2 main problems (ignoring all the syntax errors assuming that they are just here on your question but your actual code is OK)
First you are never breaking out of the while loop, you must use the break statement anywhere you want to exit the loop.
Second you are overwriting the providedname at the end of the loop, that will leave you without the actual name, the variable will be quit even after the correct name was provided.

Related

trying to simplify some boolean statements in python

I'm "newish" to python programming. I'm trying my best to make my code look nice and function well. I'm using Pycharm as my IDE. I'm doing something for myself. I play tabletop RPG's and I'm attempting to create a character creator for a game I play. I have everything working well, but Pycharm is telling me that "Expression can be simplified" and "PEP 8: E712 comparison to True should be 'if cond is not True:' or 'if not cond:'"
Here is the code in question:
fname = False
while fname != True:
new_character.firstName = input('What would you like your first name to be?\n').capitalize()
if 1 >= len(new_character.firstName) or len(new_character.firstName) > 20:
print('Name does not meet length requirements. Please try again.')
if new_character.firstName.isalpha() != True:
print('Please do not use numbers or special characters in your name. Please try again.')
if (1 < len(new_character.firstName) < 20) and (new_character.firstName.isalpha() == True):
fname = True
Pycharm is telling me that my "while fname != True:" is the part that can be simplified as well as the "if new_character.firstName.isalpha() != True:".
I've tried googling a solution for what I'm doing, but most of them are for something kinda like what I'm asking, but never with the != True portion. I've even reached out to one of my friends that's a python programmer, but I haven't heard back yet.
Again, I want to state that as it is now, the code works correctly the way it is written, I'm just wanting to understand if there is a way to make the code look cleaner/neater or do the same function and be simplified somehow.
Any pointers on how to potentially simplify those lines of code and maintain the functionality would be greatly appreciated.
Here's one way you could rewrite this code to make it easier to read, and more efficient:
# Loop until the user provides a good input
while True:
# Set a temp variable, don't constantly reassign to the new_character.firstName attribute
name = input('What would you like your first name to be?\n').capitalize()
# If the name isn't between 2 and 20 characters, start the loop over at the beginning
if not (1 < len(name) <= 20):
print('Name does not meet length requirements. Please try again.')
continue
# If the name contains anything other than letters, start the loop over at the beginning
if not name.isalpha():
print('Please do not use numbers or special characters in your name. Please try again.')
continue
# You can only reach this break if the name "passed" the two checks above
break
# Finally, assign the character name
new_character.firstName = name
One thing you could do to simplify further is to check both conditions at the same time, and print a more helpful error message that re-states the requirements explicitly:
NAME_ERROR_MESSAGE = """
Invalid name '{name}'. Your character's name
must be between 2 and 20 characters long, and
contain only letters. Please try again.
"""
while True:
name = input('What would you like your first name to be?\n').capitalize()
if (1 < len(name) <= 20) and name.isalpha():
new_character.firstName = name
break
print(NAME_ERROR_MESSAGE.format(name=name)

How to include 1st, 2nd, 3rd instead of writing it out

# extension
modify = input("Would you like to modify your recordings? Yes or No? ")
if modify == ("Yes","yes","Y","y"):
print ("OK")
if modify == ("No","no","n","N"):
print ("You may now exit the program")
print("")
name = input ("Whose score would you like to modify? Type it in with this format - Name, Age Category: ")
if name == ("Jane, Under 11"):
answer = input ("Would you like to add or delete data? ")
if name == ("Grant, Under 11"):
answer = input ("Would you like to add or delete data? ")
if name == ("Lilly, Under 11"):
answer = input ("Would you like to add or delete data? ")
if name == ("Henry, Over 11"):
answer = input ("Would you like to add or delete data? ")
if name == ("Jane, Over 11"):
answer = input ("Would you like to add or delete data? ")
if name == ("Naomi, Over 11"):
answer = input ("Would you like to add or delete data? ")
if answer == ("add" ,"Add"):
pos = input ("Type in the position(s) you would like to add: ")
elif answer == ("delete" ,"Delete", "del", "Del"):
delete = input ("Would you like to delete position or name?")
if delete == ("pos","Pos","Position","position"):
print ("Position deleted. Here is the final outcome: ",name)
elif delete == ("Name", "name"):
print ("Name deleted. There is no data now")
if pos == ('1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th', '10th','11th', '12th', '13th', '14th', '15th', '16th', '17th', '18th', '19th', '20th', '21st', '22nd', '23rd', '24th', '25th', '26th', '27th', '28th', '29th', '30th', '31st'):
print ("Posititon added. Here is their final score: ", name, " ", pos)
Hello. I am new to SO so I'm not sure if this is the correct way to do this however I am trying to answer a question where I am told to use pickle and store data inside a file. I am also told that the code should be able to let the user select a list to delete, be able to change a player position(its about a tennis competition) and be able to store the position of players in their last three tournaments. I need to do it in certain age categories
Everything works well so far however I need to do the positions as 1st 2nd 3rd and so on up to 1000. I have started writing it out(see penultimate line) but it would take extremely long to write it out so does anyone know a way to save time and solve this problem??
This is an odd little program, which will break if you don't enter answers with exactly what you're expected to enter.
I was able to get your error when I typed "No" (accidentally) after the prompt "Whose score would you like to modify?"
Since you haven't instantiated the variable answer before your if statements (as #Enes pointed out) and since none of your if statements are true, I didn't have anything stored in the answer variable, when you called
if answer == ("add" ,"Add"):...
this threw an error.
So if you fix the error that #Schlator mentioned
(Change
if modify == ("Yes","yes","Y","y"):
to
if modify in ("Yes","yes","Y","y"):
everywhere)
and if you instantiate your variable answer as Enes mentioned
(Add
answer = ""
before
name = input ("Whose score would you like to modify? Type it in with this format - Name, Age Category: ")
)
then at least your fragile little program will exit gracefully.
It appears that you are mistaken with the syntax
It shouldn't be
if modify == ("Yes","yes","Y","y"):
rather it should be
if modify in ("Yes","yes","Y","y"):
Similarly for other if conditions that you have used in other parts of the program.
The way you've written your program, you will always drop through to if answer == with answer being undefined. Your input and test sequence:
name = input ("Whose score would you like to modify? Type it in with this format - Name, Age Category: ")
if name == ("Jane, Under 11"):
cannot possibly match the choices you've given, because every input will contain a newline. You need to either include that in your test, or strip it from the input before checking.

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")

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.

NameError when programming in python

I made a program in python that is supposed to accept a name as user input. It will then check if the name given is contained inside a string that is already given and if it is then the program will print out the telephone next to that name. My code is as follows:
tilefwnikos_katalogos = "Christoforos 99111111: Eirini 99556677: Costas 99222222: George 99333333: Panayiotis 99444444: Katerina 96543217"
check=str(input("Give a name: "))
for check in tilefwnikos_katalogos:
if check=="Christoforos":
arxi=check.find("Christoforos")
elif check=="Eirini":
arxi=check.find("Eirini")
elif check=="Costas":
arxi=check.find("Costas")
elif check=="George":
arxi=check.find("George")
elif check=="Panayiotis":
arxi=check.find("Panayiotis")
elif check=="Katerina":
arxi=check.find("Katerina")
s=check.find(" ",arxi)
arxi=s
y=check.find(":",arxi)
telos=y
apotelesma=tilefwnikos_katalogos[arxi+1:telos]
print(apotelesma)
But when I try to run it, I input the name and then the following message pops up:
Traceback (most recent call last):
File "C:\Users\Sotiris\Desktop\test.py", line 16, in <module> s=check.find(" ",arxi)
NameError: name 'arxi' is not defined
What am I doing wrong?
You're getting your error because arxi isn't getting defined in the first place when then name the user gave is not present on your list.You can fix that by simply adding an unconditional else case to your if/else if bundle as pointed in the comments. But the very way you tackled this problem is faulty, storing data like this in a string is a bad idea, you want to use a dictionary:
phone_catalog = {'Christoforos': 99111111, 'Eirini': 99556677, 'Costas': 99222222, 'George':99333333, 'Panayiotis':99444444, 'Katerina': 96543217}
Also check isn't a very clear variable name, maybe you should try using something better like:
user_name = str(input("Give a name: "))
And now you can do your if/elif condition but replacing it for using dictionary logic and making sure you have a final else, like such:
if user_name in phone_catalog:
print(phone_catalog[user_name])
else:
print("Unknown user")
See how the dictionary made your life much easier and your code cleaner here? Read more on Python Data Structures.
so there are a few things you have overlooked / not going as expected, the first of which is how iterating over strings in python works:
tilefwnikos_katalogos = "Christoforos 99111111: Eirini 99556677: Costas 99222222: George 99333333: Panayiotis 99444444: Katerina 96543217"
for check in tilefwnikos_katalogos:
print(check)
#print(repr(check)) #this shows it as you would write it in code ('HI' instead of just HI)
so check can never be equal to any of the things you are checking it against, and without an else statement the variable arxi is never defined. I'm assuming you meant to use the check from the user input instead of the one in the loop but I'm not sure you need the loop at all:
tilefwnikos_katalogos = "Christoforos 99111111: Eirini 99556677: Costas 99222222: George 99333333: Panayiotis 99444444: Katerina 96543217"
check=str(input("Give a name: ")) #the str() isn't really necessary, it is already a str.
if check=="Christoforos":
arxi=check.find("Christoforos")
elif check=="Eirini":
arxi=check.find("Eirini")
elif check=="Costas":
arxi=check.find("Costas")
elif check=="George":
arxi=check.find("George")
elif check=="Panayiotis":
arxi=check.find("Panayiotis")
elif check=="Katerina":
arxi=check.find("Katerina")
else: raise NotImplementedError("need a case where input is invalid")
s=check.find(" ",arxi)
arxi=s
y=check.find(":",arxi)
telos=y
apotelesma=tilefwnikos_katalogos[arxi+1:telos]
print(apotelesma)
but you could also just see if check is a substring of tilefwnikos_katalogos and deal with other conditions:
if check.isalpha() and check in tilefwnikos_katalogos:
# ^ ^ see if check is within the string
# ^ make sure the input is all letters, don't want to accept number as input
arxi=check.find(check)
else:
raise NotImplementedError("need a case where input is invalid")
although this would make an input of C and t give Cristoforos' number since it retrieves the first occurrence of the letter. An alternative approach which includes the loop (but not calling the variable check!) would be to split up the string into a list:
tilefwnikos_katalogos = "..."
check = input(...)
for entry in tilefwnikos_katalogos.split(":"):
name, number = entry.strip().split(" ")
if check == name:
apotelesma=number
break
else:
raise NotImplementedError("need a case where input is invalid")
although if you are going to parse the string anyway and you may use the data more then once it would be even better to pack the data into a dict like #BernardMeurer suggested:
data = {}
for entry in tilefwnikos_katalogos.split(":"):
name, number = entry.strip().split(" ")
data[name] = number #maybe use int(number)?
if check in data:
apotelesma = data[check]
else:
raise NotImplementedError("need a case where input is invalid")

Categories