1
votes

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.

6
Your are doing recursive calls, that's why the congratularory reponse it's printed 3 timesRobin Curbelo

6 Answers

3
votes

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()
2
votes

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...

2
votes

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()
2
votes

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.

1
votes

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.

1
votes

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)