I am trying to perform something that has certainly been asked several times before (specifically Asking the user for input until they give a valid response, but I'm either trying to do something too complex or not thinking about my loops the correct way.
In the code below, I am trying to do a few things:
loan_ids
)In the second func, I am trying to combine the first one and then also ask the user to confirm the loan_ids
before cutting out:
y
, then end the loopn
, go back to the first function and ask againI'm trying not to violate the Don't Repeat Yourself principle, but for the life of me I can't figure out the placement of the loops. I'm also relatively new to python and programming structure, so open to idiomatic comments on the design as well
def get_unique_loans_from_user():
"""Get list of loan_ids from user
This function is mean to capture raw loan_ids a user wishes to look up.
Returns tuple of unique loan_ids
"""
loan_ids = []
while True:
loan_id = raw_input('> Loan Id: ')
# If nothing entered, exit
if len(loan_id)==0:
break
# Make sure an integer was entered
else:
try:
int(loan_id)
except ValueError:
print loan_id + " is not a real integer, so likely not a valid loan id"
continue
# if an integer was entered, append to running list as an integer and continue
# We only need to return the unique list of loan ids
else:
loan_ids.append(int(loan_id))
# Convert unique list of loans to tuple to use in SQL
loans = tuple(np.unique(loan_ids))
# Return the tuple of loans
return loans
And the second piece - the way it's currently written forces the same result when a user enters anything but y
- I'm trying to cause different behavior depending on whether the use has invalid input vs. actually confirms the loan_ids
are incorrect. I also have used an extra break statement at the end, which I'm fairly sure is not best practice
def confirm_loan_ids():
""" Confirm the list of loan ids is what the user wanted"""
while True:
# Get loan ids from user through raw input
ids = get_unique_loans_from_user()
# Print out the ids to the user
print "Printing loan ids. There are {0} ids".format(len(ids))
print ids
# Confirm with user these are the correct ids
answer = raw_input('> Are these the loan ids you expected? [y/n] ')
# If user confirms correct, and continue
if answer == 'y':
print "\nExcellent - moving on\n"
print "Here are your loan ids:"
print ids
break
# If the answer is n, repeat the question
elif answer == 'n':
print "\n-------------> Let\'s try again\n"
continue
# If answer is not no or yes, ask again
elif (len(answer) == 0) or (answer not in ('y','n')):
print "Please enter only y or n"
continue
else:
print "This is only a test"
# The If loop only breaks when the answer is 'y'
break
return ids
Try this. It reduces some of the requirements to use continue
, instead letting the loop naturally iterate again. This reduces visual noise in the code.
For your second function, you can again simplify the logic to remove the need to use continue, instead only breaking when the input is good.
The code needs to loop again for the yes/no confirmation, so to avoid issues with having to break out of nested loops, the yes/no loop is in another function. This function won't return until a valid input is received.
Hopefully this gives you some slightly clearer logic to work with?
You can reinstate your numpy.unique
function if you want instead of set
, but I don't generally use numpy
and importing it just for that purpose seems a bit excessive I used set
instead. I don't know your exact requirements, so don't know if set
or numpy.unique
is more appropriate.
from __future__ import print_function
def get_unique_loans_from_user():
loan_ids = []
while True:
loan_id = raw_input('> Loan Id: ')
try:
loan_id_int = int(loan_id)
if loan_id_int == 0:
break
loan_ids.append(loan_id_int)
except ValueError:
print("%s is not a real integer, so likely not a valid loan id" % loan_id)
# note: this will alter the order.
return tuple(set(loan_ids))
def yesnoconfirm(msg):
while True:
answer = raw_input(msg)
if answer in ('y', 'n'):
return answer
else:
print('not a valid input')
def confirm_loan_ids():
while True:
ids = get_unique_loans_from_user()
print("Printing loan ids. There are {0} ids".format(len(ids)))
print(ids)
answer = yesnoconfirm('> Are these the loan ids you expected? [y/n] ')
if answer == 'y':
break
elif answer == 'n':
print("\n-------------> Let\'s try again\n")
else:
print("oops something went wrong")
print("\nExcellent - moving on\n")
print("Here are your loan ids:")
print(ids)
return ids
print(get_unique_loans_from_user())
raw_input('continue?')
confirm_loan_ids()