-1
import os
#Must Access this to continue.
def main():
    while True:
        PassWord = input ("Enter Password: ")

        if PassWord == 'hello':
            loop = 0
            print ("Login successful!")
            logged()

        else:
            print ("Password did not match!")

def logged():
    print ("Welcome to the second half of the program")


    def main():
        while True:
            Name = input ("What is your name? ")

            if Name == 'Cher' or 'Madonna':
                print ("May I have your autograph, please?")
                logged()

            else:
                print ("(input name), that's a nice name.")

    
main()

I want the program to move onto the second loop after I enter the correct password. Right now whether I get the password right or wrong it loops back which makes it so I can not access the second part of the code.

ForceBru
  • 43,482
  • 10
  • 63
  • 98
  • 1
    Calling two functions `main` is a recipe for confusion. Suggest you rename the one inside `logged` to something (anything) different – DisappointedByUnaccountableMod May 19 '21 at 21:48
  • 2
    Also, the nested `main` inside `logged` is never called, so that's all just dead code. – Samwise May 19 '21 at 21:49
  • 1
    Please repeat [on topic](https://stackoverflow.com/help/on-topic) and [how to ask](https://stackoverflow.com/help/how-to-ask) from the [intro tour](https://stackoverflow.com/tour). In particular, this post implicitly includes several questions: you made multiple mistakes before you started testing. Please supply the expected [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) (MRE): reduce this to *one* problem and repost. Your post includes much that doesn't contribute to the problem, only to your confusion. Clarify both at once. – Prune May 19 '21 at 22:33
  • 1
    Also make sure that you've done the appropriate research. Make sure that each task in your code works before you add the next. In particular, see [input until valid](https://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response). – Prune May 19 '21 at 22:36

3 Answers3

2

You're mixing and matching two types of loop (while and a recursive call), and you're never breaking out of the while loop; your recursive call also doesn't loop the way you seem to be trying to have it loop because it uses a nested function that's never called.

Here's a simpler version that doesn't involve any recursion:

def login() -> None:
    """Loops until the correct password is entered."""
    while True:
        if input("Enter Password: ") == 'hello':
            print ("Login successful!")
            return
        print ("Password did not match!")

def ask_name() -> None:
    """Ask the user for their name until it's not someone famous."""
    while True:
         name = input("What is your name? ")
         if name not in ('Cher', 'Madonna'):
            print (f"{name}, that's a nice name.")
            return
         print ("May I have your autograph, please?")


if __name__ == '__main__':
    login()
    print ("Welcome to the second half of the program")
    ask_name()

You might notice that these two functions look very similar -- this is a good clue that you could make them be a single function:

from typing import Callable

def prompt_until_valid(
    prompt: str, 
    validator: Callable[[str], bool],
    validation_error: str
) -> str:
    """Prompt until a valid value is entered."""
    while True:
        answer = input(prompt)
        if validator(answer):
            return answer
        print(validation_error)

if __name__ == '__main__':
    prompt_until_valid(
        "Enter Password: ",
        lambda x: x == 'hello',
        "Password did not match!"
    )
    print("Login successful!")

    print ("Welcome to the second half of the program")

    name = prompt_until_valid(
        "What is your name? ",
        lambda x: x not in ('Cher', 'Madonna'),
        "May I have your autograph, please?"
    )
    print(f"{name}, that's a nice name.")
Samwise
  • 68,105
  • 3
  • 30
  • 44
  • I appreciate you simplifying this for me. I wish for it not say physically say "input name" but to actually say "Bob, that's a nice name." or whatever it may be. Also what needs to be done to the second function to stop it from being in a loop? – Gnarles Barkley May 19 '21 at 22:01
  • Remove `while True:` and it won't loop. – ggorlen May 19 '21 at 22:07
0

The only action that your logged() function takes is to print out a message. It also defines an internal routine, but doesn't execute it. So logged() prints its message and exits, and the loop it was called from in (top-level) main() continues.

I'm wondering - was the loop = 0 statement supposed to terminate the while loop in main(), in some earlier draft of the program?

Joffan
  • 1,485
  • 1
  • 13
  • 18
0

There are a couple of bugs unrelated to your main question:

  • ("(input name), that's a nice name.") doesn't do variable interpolation. You can use an f-string print(f"{name}, that's a nice name.")
  • if Name == 'Cher' or 'Madonna': won't work as you think because the condition is always true. It evaluates as if (Name == 'Cher') or ('Madonna'): and the nonempty string 'Madonna' is always truthy. if name in ["Cher", "Madonna"]: fixes the job by checking list membership. if name == "Cher" or name == "Madonna": also works.

The overall flow you want isn't entirely clear -- I assume the second while loop wasn't intended, because it'd be strange to prompt a user until their name changes or they have to guess "Madonna" or "Cher" to make progress.

In any case, my recommendation is to abstract out the idea of "asking the user for input until they give an appropriate response". This makes it much simpler to validate input and get rid of the loop and block necessary to do so in your main line code.

For example,

def get_response(prompt, error_message=None, predicate=bool):
    while True:
        response = input(prompt)

        if predicate(response):
            return response

        if error_message is not None:
            print(error_message)

def main():
    get_response(
        prompt="Enter Password: ", 
        error_message="Password did not match!", 
        predicate=lambda x: x == "hello"
    )
    print("Login successful!")
    print("Welcome to the second half of the program")

    name = get_response(
        prompt="What is your name? ", 
        error_message="At least one character needed!"
    )

    if name in ["Cher", "Madonna"]:
        print("May I have your autograph, please?")
    else:
        print(f"{name}, that's a nice name.")

if __name__ == "__main__":
    main()

Sample run:

Enter Password: blah
Password did not match!
Enter Password: hello
Login successful!
Welcome to the second half of the program
What is your name?
At least one character needed!
What is your name?
At least one character needed!
What is your name? blarrghg
blarrghg, that's a nice name.

As you add complexity and begin adding branches and tracking state, for example, whether the user's name is "Madonna" or "Cher" or something else that can influence future questions, you might want to look into a decision tree or state machine (nice if states can be reached from multiple locations or are repeatable, like re-entering a room).

Without care, you can wind up with tons of nested if/elif/else which will make the code unpleasant, even if they're buried in many functions.

I'm probably getting ahead of myself though.

ggorlen
  • 44,755
  • 7
  • 76
  • 106