Program prints ouput twice - python

I have made a program which shows contact when contact name is given but the contact not found statement is coming twice
answer=""
while answer!= "yes":
contact_name = input("Entername: ")
contacts = {'Mom': 9469211475, 'Dad': 9419198443}
for name in contacts:
if name == contact_name:
print("Contact number is: ", contacts[name])
else:
print("Contact not found")
answer = input("Do you wish to exit? Please Enter Yes or No: ").lower()
print("Thank you")

Your code is currently an anti-pattern: you're using a dict but still looping over all its contents (with an O(n) complexity) to check if a certain key exists.
You don't need to loop the names if you're using a dict... Simply check if the name exists in the dict (with an O(1) complexity) and if it's not, print accordingly. In general, the pattern:
for x in iterable:
if x == y:
# do something with y
break
Is usually equivalent to:
if y in iterable:
# do something with y
So in your case:
contacts = {'Mom': 9469211475, 'Dad': 9419198443}
while answer != "yes":
contact_name = input("Entername: ")
if contact_name in contacts:
print("Contact number is: ", contacts[contact_name])
else:
print("Contact not found")
answer = input("Do you wish to exit? Please Enter Yes or No: ").lower()
print("Thank you")
Or, if you're comfortable with exception handling, this saves the double look-up:
contact_name = input("Entername: ")
try:
print("Contact number is: ", contacts[contact_name])
except KeyError:
print("Contact not found")

The loop for name in contacts: will iterate over the two elements in the contacts list. Hence, the code in the body of the for loop executes twice.
What you should do instead, is remove the else branch of the if statement and check once after the for loop completes whether the contact has been found or not.
A simple way to do this is by setting a new variable found to False before the loop, updating to True inside the loop if the contact is found and then checking the value of flag after the loop terminates.

You can set count of loop and change it every time it loops. then compare it with length of the dict. if it's same as the length of the dict, then that means the word is not found.
Like this:
answer=""
while answer!= "yes":
contact_name = input("Entername: ")
contacts = {'Mom': 9469211475, 'Dad': 9419198443}
loop = 0
for name in contacts:
loop += 1
if loop >= len(contacts):
print("Contact not found")
break
if name == contact_name:
print("Contact number is: ", contacts[name])
break
answer = input("Do you wish to exit? Please Enter Yes or No: ").lower()
print("Thank you")
Or just use for else
answer=""
while answer!= "yes":
contact_name = input("Entername: ")
contacts = {'Mom': 9469211475, 'Dad': 9419198443}
for name in contacts:
if name == contact_name:
print("Contact number is: ", contacts[name])
break
else:
print("Contact not found")
answer = input("Do you wish to exit? Please Enter Yes or No: ").lower()
print("Thank you")

Related

How to have input in Python only take in string and not number or anything else only letters

I am a beginner in Python so kindly do not use complex or advanced code.
contact = {}
def display_contact():
for name, number in sorted((k,v) for k, v in contact.items()):
print(f'Name: {name}, Number: {number}')
#def display_contact():
# print("Name\t\tContact Number")
# for key in contact:
# print("{}\t\t{}".format(key,contact.get(key)))
while True:
choice = int(input(" 1. Add new contact \n 2. Search contact \n 3. Display contact\n 4. Edit contact \n 5. Delete contact \n 6. Print \n 7. Exit \n Enter "))
#I have already tried
if choice == 1:
while True:
try:
name = str(input("Enter the contact name "))
if name != str:
except ValueError:
continue
else:
break
while True:
try:
phone = int(input("Enter number "))
except ValueError:
print("Sorry you can only enter a phone number")
continue
else:
break
contact[name] = phone
elif choice == 2:
search_name = input("Enter contact name ")
if search_name in contact:
print(search_name, "'s contact number is ", contact[search_name])
else:
print("Name is not found in contact book")
elif choice == 3:
if not contact:
print("Empty Phonebook")
else:
display_contact()
elif choice == 4:
edit_contact = input("Enter the contact to be edited ")
if edit_contact in contact:
phone = input("Enter number")
contact[edit_contact]=phone
print("Contact Updated")
display_contact()
else:
print("Name is not found in contact book")
elif choice == 5:
del_contact = input("Enter the contact to be deleted ")
if del_contact in contact:
confirm = input("Do you want to delete this contact Yes or No? ")
if confirm == 'Yes' or confirm == 'yes':
contact.pop(del_contact)
display_contact
else:
print("Name is not found in phone book")
elif choice == 6:
sort_contact = input("Enter yes to print your contact")
if sort_contact in contact:
confirm = input("Do you want to print your contact Yes or No? ")
if confirm == 'Yes' or confirm == 'yes':
strs = [display_contact]
print(sorted(strs))
else:
print("Phone book is printed.")
else:
break
I tried but keep getting errors and I can't fiugre out how to make it only take string or letter as input and not numbers.
if choice == 1:
while True:
try:
name = str(input("Enter the contact name "))
if name != str:
except ValueError:
continue
else:
break
it is not working my code still accepts the ans in integer and string.
I am a beginner so I might have made a lot of mistakes. Your patience would be appreciated.
You can use a regex with re.fullmatch:
import re
while True:
name = input("Enter the contact name ")
if re.fullmatch(r'[a-zA-Z]+', name):
break
Or use the case-insensitive flag: re.fullmatch(r'[a-z]+', name, flags=re.I):
As you noted that you are a beginner, I'm adding this piece of code
as a "custom-made" validation, just so you can check how you would do something like this by your own .
Note: #mozway gave a MUCH BETTER solution, that is super clean, and I recommend it over this one.
def valid_input(input: str):
# Check if any char is a number
for char in input:
if char.isdigit():
print('Numbers are not allowed!')
return False
return True
while True:
name = input("Enter data:")
if valid_input(name):
break
I found this answer from another website:
extracted_letters = " ".join(re.findall("[a-zA-Z]+", numlettersstring))
First, import re to use the re function.
Then let's say that numlettersstring is the string you want only the letters from.
This piece of code will extract the letters from numlettersstring and output it in the extracted_letters variable.

How do I stop my program from reading the second while loop when not needed?

I have some homework which I'm not sure how to finish.
The task given was to make a script which would ask the user to enter his name, after entering it, the script would check if the name entered matches with any of the names on a pre-existing list.
If the name matches the script would ask the user if they would like to delete the name off the list or keep it.
If the name doesn't match with any names on the list, it asks if the user if they'd like to add it on it.
The script should write the list of names in the end.
I wrote it like this:
name = input("Please enter your name:")
lk = ['Peti','John','Mary','Claire','Hellen']
while name in lk:
print("Your name is already in our list.")
if name in lk:
bris = input("Would you like to delete your name off our list?[Y/N]:")
if bris == "Y":
lk.remove(name)
print("Your name was removed.")
print(lk)
break
elif bris == "N":
print("OK!",name,"Your name will be saved.")
print(lk)
break
while name not in lk:
doda = input("Your name is not registered on our list, would you like to add it?[Y/N]:")
if doda == "Y":
lk.append(name)
print("Your name has been added.")
print(lk)
elif doda == "N":
print("Alright, goodbye",name,"!")
break
Issue is, that I have no idea how to stop it once the user chooses to delete their name off the list, it always reads the next while because the deleted name is no longer on the list.
Also, I am very sorry if this looks like poo poo I'm new to coding
If the user needs to be entered only once, why using loop?
name = input("Please enter your name:")
lk = ['Peti','John','Mary','Claire','Hellen']
if name in lk:
print("Your name is already in our list.")
bris = input("Would you like to delete your name off our list?[Y/N]:")
if bris == "Y":
lk.remove(name)
print("Your name was removed.")
print(lk)
elif bris == "N":
print("OK!",name,"Your name will be saved.")
print(lk)
else:
doda = input("Your name is not registered on our list, would you like to add it?[Y/N]:")
if doda == "Y":
lk.append(name)
print("Your name has been added.")
print(lk)
elif doda == "N":
print("Alright, goodbye",name,"!")
Your loop structure is the root of the issue. Since you're using while loops I'm assuming you want your script to loop and keep asking for new inputs. In this case you'll want one loop that you can break out of when you're done entering names based on some user input:
lk = ['Peti','John','Mary','Claire','Hellen']
while keep_looping = 'Y':
# check a name
name = input("Please enter a name: ")
if name in lk:
# name in list logic here
else:
# name not in list logic here
# ask user if the loop should continue. Entering 'N' will break the loop
keep_looping = input("Would you like to try another name? (Y/N): ")
You can reuse your existing logic for checking for names in the list and adding/removing, but you'll also want the name checking logic as an if/else block so only one condition can be met per loop. Otherwise you'll run into the same issue when a name exists and gets removed.
There are other optimizations you can do but I'll let you figure those out on your own.
name = input("Please enter your name:")
lk = ['Peti','John','Mary','Claire','Hellen']
if name in lk:
print("your name already present in list")
k= input(("would you like to delete your name from the list: [y/n]:"))
if k=="y":
lk.remove(name)
print("your name is deleted from the list")
print(lk)
else:
print("your name kept as it is in the list")
else:
print("your name is not present in list")
k= input(("would you like to add your name to the list: [y/n]:"))
if k=="y":
lk.append(name)
print("your name is added to the list")
print(lk)
else:
print("list is kept as it is")
print(lk)

Loop an if statement if the else condition is met

So I have an If-elif statement that I want to print some text and loop if the else condition is met. Here is the code:
print("Search Options:\n1. s - Search by keyword in general\n2. u - Search for specific user data\n3. kwin - Search a keyword in a specific user\n4. allin - Search for all data by and mentioning a user")
search_mode = input("How would you like to search?: ")
if "s" in search_mode:
kwsearch = input("What Keyword do you want to use?: ")
elif "u" in search_mode:
username = input("What is the username?: ")
elif "kwin" in search_mode:
kwinuser = input("What is the username?: ")
kwinword = input("What is the keyword?: ")
elif "allin" in search_mode:
allinuser = input("What is the username?: ")
else:
print("Error. Please check spelling and capitalization")
When people mess up and don't put one of the options properly, I want to loop back to the if statement so that when they put in the right one, the loop will end and the rest of the code will continue.
I tried a for loop and wrapped it all as a function but it would end up in an infinite loop of printing the error message. Is there a way to do it with a while loop? Do I need to block it ad a function to repeat it?
Thanks in advance!
In Python, the most idiomatic thing I see for this is while True:
while True:
search_mode = input("How would you like to search?: ")
if "s" in search_mode:
kwsearch = input("What Keyword do you want to use?: ")
elif "u" in search_mode:
username = input("What is the username?: ")
elif "kwin" in search_mode:
kwinuser = input("What is the username?: ")
kwinword = input("What is the keyword?: ")
elif "allin" in search_mode:
allinuser = input("What is the username?: ")
else:
print("Error. Please check spelling and capitalization")
continue
break
You can use a while loop and break statement. You can also reduce the elif statement as I see duplicate code.
Also, you can reduce the user error by converting the search_mode to lowercase.
print("Search Options:\n1. s - Search by keyword in general\n2. u - Search for
specific user data\n3. kwin - Search a keyword in a specific user\n4. allin -
Search for all data by and mentioning a user")
search_mode = input("How would you like to search?: ")
while True:
if "s" in search_mode.lower():
kwsearch = input("What Keyword do you want to use?: ")
break
elif search_mode.lower() in ('u','kwin','allin'):
username = input("What is the username?: ")
if "kwin" in search_mode.lower():
kwinword = input("What is the keyword?: ")
break
else:
print("Error. Please check spelling and capitalization")
search_mode = input("How would you like to search?: ")
The code enters the while loop after accepting value into variable search_mode.
If the value is 's', it asks for the keyword and breaks the loop.
if the value is not 's', then it checks if the value is 'u' or 'kwin' or 'allin'. If it is any of these, then it asks for the username. If the value is kwin, it also asks for keyword. Then it breaks the loop.
If the value is none of the above, it prints the error statement and asks the user the question again. It goes into the loop again with the new value from the user and checks the conditions again. It will exit only when the if or elif statement is true. Hope this helps.

Python: Problems when calling outside function

I'm a beginner to Python, and am having problems with a function. I am making a program in which I have many parameters for the user to choose from and I need to allow them to confirm or deny their choices. Here is a simplified code section that represents my issue.
my code:
def confirm(function):
while True:
answer = raw_input('Are you sure? ')
if answer == 'yes':
break
elif answer == 'no':
return function() # if the user wants to change their name, recall function
else:
continue # to reprompt user if the answer is not "yes" or "no"
def your_name():
while True:
name = raw_input("What is your name? ")
if not name:
continue # to reprompt user if they do not enter anything
else:
confirm(your_name)
print 'Congratulations! You have a name!'
break
your_name()
When running this program, it will print the congratulatory string the same amount of times that answer received an input.
my output:
What is your name? Bastion
Are you sure? no
What is your name? Artex
Are you sure? no
What is your name? Falcor
Are you sure? yes
Congratulations! You have a name!
Congratulations! You have a name!
Congratulations! You have a name!
My intention is for the congratulatory message to be printed just one time. How can I edit my function(s) in order to achieve this?
What I've tried:
I have attempted all of these, using the exact same input values I used in my output block above.
Within the section of confirm(function) that says:
if answer == 'no':
return function()
I've tried changing it to:
if answer == 'no':
function()
In the output, this will ask for the answer raw_input 3 times, posting the congratulatory message after each input. If I write the code in this way:
if answer == 'no':
print function()
It will print the congratulatory response 3 times and print None on a separate line below for each time. I am looking for an elegant, clean format so this will not do.
So your problem is you are creating a kind of recursive function without meaning to, you don't need to pass the function to be called again as you are already inside the function. I would suggest the following:
def confirm():
while True:
answer = raw_input('Are you sure? ')
if answer == 'yes':
return True
if answer == 'no':
return False
else:
continue # to reprompt user if the answer is not "yes" or "no"
def your_name():
while True:
name = raw_input("What is your name? ")
if not name:
continue # to reprompt user if they do not enter anything
elif confirm():
print 'Congratulations! You have a name!'
break
your_name()
I think the cleanest way is to change your_name to:
def your_name(toplevel=False):
while True:
name = raw_input("What is your name? ")
if not name:
continue # to reprompt user if they do not enter anything
else:
confirm(your_name)
if toplevel: print 'Congratulations! You have a name!'
break
and the very first call from the top level to your_name(True).
There are other ways, but they require global variables (ecch:-) or even dirtier tricks to find out if the function has been called from the top level; telling it explicitly is way cleaner...
Because of the style recursion you're doing (kudos on that) you end up invoking the your_name() function once each time they fill an answer.
I'd try something more like this:
def confirm():
answer = ''
while answer == '':
answer = raw_input('Are you sure? ')
if answer == 'yes':
return True
elif answer == 'no':
return False
else:
answer = ''
def your_name():
name = ''
while name == '':
name = raw_input("What is your name? ")
if confirm():
print 'Congratulations! You have a name!'
else:
your_name()
your_name()
I think you don't have to use all those "recursive" calls, try this:
def your_name():
flag = True
while flag:
name = raw_input("What is your name? ")
if name:
while True:
answer = raw_input('Are you sure? ')
if answer == 'yes':
flag = False
break
elif answer == 'no':
break
print 'Congratulations! You have a name!'
your_name()
Using an inner loop for asking if the user is sure. With the use of a flag to determine whenever or not the main "What is your name? " question cycle is over.
You can just put the print 'Congratulations! You have a name!' inside your confirmation() function instead of your_name() so it will be something like this:
def confirm(function):
while True:
answer = raw_input('Are you sure? ')
if answer == 'yes':
print 'Congratulations! You have a name!'
break
elif answer == 'no':
return function() # if the user wants to change their name, recall function
else:
continue # to reprompt user if the answer is not "yes" or "no"
def your_name():
while True:
name = raw_input("What is your name? ")
if not name:
continue
else:
confirm(your_name)
break
your_name()
BTW, I also modify your conditional syntax in the first function so that the program won't go through two if statements.
This solution is relatively succinct. It loops requesting your name while 'name' is an empty string. When requesting confirmation, it resets name to an empty string and thus continues the loop unless the user confirms 'yes'. It then prints the user's name to confirm its assignment.
def your_name():
name = ''
while name == '':
name = raw_input("What is your name? ")
answer = raw_input('Are you sure (yes or no)? ') if name != '' else 'no'
name = '' if answer != 'yes' else name
print 'Congratulations {0}! You have a name!'.format(name)

Python While Statements

I'm a bit confused on the logic of doing this.
I want the user to be able to input the number of items they have, and then ask them at the end if they are done. Right now I'm asking after every single item, and I don't like it.
How should I modify this code to get what I want?
Input:
if next1 == "2":
next2=input("How many would you like to add? ")
val = int(next2)
print("")
count = 0
while count < int(next2):
count = count + 1
next3=input(str(count) + ". Input: ")
print("")
check=input("Are you sure? (Y/N) ")
while check not in ("YyYesNnNo"):
check=input("Are you sure? (Y/N) ")
if check in ("YyYes"):
add(next3)
home()
elif check in ("NnNo"):
sort(numbers)
home()
Function:
def add(next2):
numbers.append(next2)
sort(numbers)
home()
Okay, well generally you might do something like this
def confirm_with_user():
user_data = ""
while user_data not in "YyYesNnNo":
user_data = input("Are you sure? (Y/N) ")
return user_data.lower() in "yes":
Then at the point in your code when you want to confirm with your user you just do
if confirm_with_user():
#proceed...
else:
#They don't want to proceed

Categories

Resources