Is there a better way to evaluate user inputs without a 'for' loop and changing a checker from False to True?











up vote
4
down vote

favorite












Very new to python and have been, as an exercise, doing a text-based version of a board game (I'm an avid board gamer).



There are obviously lots of places for the user to input something, and naturally I need to evaluate those inputs and make sure they are valid.



I learned about using a True/False check and for loops from this site (thanks!) and now that I've done them so much I was wondering if there was a better way - they get a little crazy if they are nested and I want to to my best to adhere to those Zen-like Python rules.



Here is what I mean, in a simple example, using generic code so it makes sense (not all of you may know the rules of this board game!)



The goal is to make sure the code loops until a color or "none" is given. I know this accomplishes that, i'm just wondering if there is a more streamlined way that I haven't learned yet.



colors = ["red", "green", "white", "blue", "yellow"]

for color in colors:
print(f"You can choose {color}.")

choice = input("Which color would you choose? (input a color or 'none' : ")
checker = False

while not checker:
if choice not in colors:
choice = input("That's not one of your options. Choose again: ")

elif choice == "none":
print("You don't want a color. That's fine.")
checker = True

else:
print("You chose {color}! Have fun!")
checker = True









share|improve this question




















  • 3




    this looks reasonable ...
    – Joran Beasley
    Nov 20 at 0:40










  • Think about a full-blown argument parser like argparse or click - they don't need to be used on the program's command-line argument. Even if you don't actually use one of them, the mindset may be useful.
    – o11c
    Nov 20 at 0:48















up vote
4
down vote

favorite












Very new to python and have been, as an exercise, doing a text-based version of a board game (I'm an avid board gamer).



There are obviously lots of places for the user to input something, and naturally I need to evaluate those inputs and make sure they are valid.



I learned about using a True/False check and for loops from this site (thanks!) and now that I've done them so much I was wondering if there was a better way - they get a little crazy if they are nested and I want to to my best to adhere to those Zen-like Python rules.



Here is what I mean, in a simple example, using generic code so it makes sense (not all of you may know the rules of this board game!)



The goal is to make sure the code loops until a color or "none" is given. I know this accomplishes that, i'm just wondering if there is a more streamlined way that I haven't learned yet.



colors = ["red", "green", "white", "blue", "yellow"]

for color in colors:
print(f"You can choose {color}.")

choice = input("Which color would you choose? (input a color or 'none' : ")
checker = False

while not checker:
if choice not in colors:
choice = input("That's not one of your options. Choose again: ")

elif choice == "none":
print("You don't want a color. That's fine.")
checker = True

else:
print("You chose {color}! Have fun!")
checker = True









share|improve this question




















  • 3




    this looks reasonable ...
    – Joran Beasley
    Nov 20 at 0:40










  • Think about a full-blown argument parser like argparse or click - they don't need to be used on the program's command-line argument. Even if you don't actually use one of them, the mindset may be useful.
    – o11c
    Nov 20 at 0:48













up vote
4
down vote

favorite









up vote
4
down vote

favorite











Very new to python and have been, as an exercise, doing a text-based version of a board game (I'm an avid board gamer).



There are obviously lots of places for the user to input something, and naturally I need to evaluate those inputs and make sure they are valid.



I learned about using a True/False check and for loops from this site (thanks!) and now that I've done them so much I was wondering if there was a better way - they get a little crazy if they are nested and I want to to my best to adhere to those Zen-like Python rules.



Here is what I mean, in a simple example, using generic code so it makes sense (not all of you may know the rules of this board game!)



The goal is to make sure the code loops until a color or "none" is given. I know this accomplishes that, i'm just wondering if there is a more streamlined way that I haven't learned yet.



colors = ["red", "green", "white", "blue", "yellow"]

for color in colors:
print(f"You can choose {color}.")

choice = input("Which color would you choose? (input a color or 'none' : ")
checker = False

while not checker:
if choice not in colors:
choice = input("That's not one of your options. Choose again: ")

elif choice == "none":
print("You don't want a color. That's fine.")
checker = True

else:
print("You chose {color}! Have fun!")
checker = True









share|improve this question















Very new to python and have been, as an exercise, doing a text-based version of a board game (I'm an avid board gamer).



There are obviously lots of places for the user to input something, and naturally I need to evaluate those inputs and make sure they are valid.



I learned about using a True/False check and for loops from this site (thanks!) and now that I've done them so much I was wondering if there was a better way - they get a little crazy if they are nested and I want to to my best to adhere to those Zen-like Python rules.



Here is what I mean, in a simple example, using generic code so it makes sense (not all of you may know the rules of this board game!)



The goal is to make sure the code loops until a color or "none" is given. I know this accomplishes that, i'm just wondering if there is a more streamlined way that I haven't learned yet.



colors = ["red", "green", "white", "blue", "yellow"]

for color in colors:
print(f"You can choose {color}.")

choice = input("Which color would you choose? (input a color or 'none' : ")
checker = False

while not checker:
if choice not in colors:
choice = input("That's not one of your options. Choose again: ")

elif choice == "none":
print("You don't want a color. That's fine.")
checker = True

else:
print("You chose {color}! Have fun!")
checker = True






python python-3.x






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 at 0:39









cricket_007

77.8k1142108




77.8k1142108










asked Nov 20 at 0:37









Jonathan

314




314








  • 3




    this looks reasonable ...
    – Joran Beasley
    Nov 20 at 0:40










  • Think about a full-blown argument parser like argparse or click - they don't need to be used on the program's command-line argument. Even if you don't actually use one of them, the mindset may be useful.
    – o11c
    Nov 20 at 0:48














  • 3




    this looks reasonable ...
    – Joran Beasley
    Nov 20 at 0:40










  • Think about a full-blown argument parser like argparse or click - they don't need to be used on the program's command-line argument. Even if you don't actually use one of them, the mindset may be useful.
    – o11c
    Nov 20 at 0:48








3




3




this looks reasonable ...
– Joran Beasley
Nov 20 at 0:40




this looks reasonable ...
– Joran Beasley
Nov 20 at 0:40












Think about a full-blown argument parser like argparse or click - they don't need to be used on the program's command-line argument. Even if you don't actually use one of them, the mindset may be useful.
– o11c
Nov 20 at 0:48




Think about a full-blown argument parser like argparse or click - they don't need to be used on the program's command-line argument. Even if you don't actually use one of them, the mindset may be useful.
– o11c
Nov 20 at 0:48












3 Answers
3






active

oldest

votes

















up vote
1
down vote













You could define a generic function if you find yourself repeating the same things



def prompt_for_valid_input(options):
while True:
print(f"You can choose one of {options}.")
choice = input("Which would you choose? (or 'none' : ")
if choice == "none" and "none" not in options:
print("You didn't pick anything. That's fine.")
return None
elif choice in options:
return choice
else:
print("That's not one of your options. Choose again. ")

colors = ["red", "green", "white", "blue", "yellow"]
color = prompt_for_valid_input(colors)
if color is not None:
print(f"You chose {color}! Have fun!")

numbers = [1, 10, 100]
num = prompt_for_valid_input(numbers)
if num is not None:
print(f"You chose {num}! Have fun!")


So "without a while/for loop", not really. Without a sentinel variable, yes, if the conditions are simple enough.






share|improve this answer





















  • Thanks for this, I like this idea. In my code, often times entering a certain input launches a function which itself might have more input validators. I like this idea and can probably implement it wisely in the right spots.
    – Jonathan
    Nov 20 at 0:54


















up vote
0
down vote













you can abstract it out to a generic validated input method



def validated_input(prompt,validation_method,error_message):
while True:
result = input(prompt)
if validation_method(result):
return result
print(error_message)


choices = ['red','green','blue','none']
validator = lambda test:test.lower().strip() in choices
prompt = "Enter A Color(one of Red, Green, Blue, or None):"
error_message = "Please enter a valid color or None!"

print(validated_input(prompt,validator,error_message))


its arguable whether this is "better"






share|improve this answer





















  • Thanks Jordan. I see now how a function like this can actually help me a lot. Often my validations lead to a function, and sometimes those have more validations. I'll play with these kind of constructions and see if i can improve the code!
    – Jonathan
    Nov 20 at 0:56










  • *Joran! want to get your name right.
    – Jonathan
    Nov 20 at 1:12


















up vote
0
down vote













Usually how you wrote your code is considered pretty "normal" and straightforward which is good. The issue is that you would want the looping part of your code to repeat till it has met its expectation. So a conditional looping event is necessary. If you really want you can simplify it a little by making a break statement for example:



x = 0
while True:
if x == 12:
break;
else:
x = x + 1
print(x)


This will create a infinite loop until the condition you are looking for is met and then it will break out of the loop. Make sure you have your escape condition though.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384614%2fis-there-a-better-way-to-evaluate-user-inputs-without-a-for-loop-and-changing%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote













    You could define a generic function if you find yourself repeating the same things



    def prompt_for_valid_input(options):
    while True:
    print(f"You can choose one of {options}.")
    choice = input("Which would you choose? (or 'none' : ")
    if choice == "none" and "none" not in options:
    print("You didn't pick anything. That's fine.")
    return None
    elif choice in options:
    return choice
    else:
    print("That's not one of your options. Choose again. ")

    colors = ["red", "green", "white", "blue", "yellow"]
    color = prompt_for_valid_input(colors)
    if color is not None:
    print(f"You chose {color}! Have fun!")

    numbers = [1, 10, 100]
    num = prompt_for_valid_input(numbers)
    if num is not None:
    print(f"You chose {num}! Have fun!")


    So "without a while/for loop", not really. Without a sentinel variable, yes, if the conditions are simple enough.






    share|improve this answer





















    • Thanks for this, I like this idea. In my code, often times entering a certain input launches a function which itself might have more input validators. I like this idea and can probably implement it wisely in the right spots.
      – Jonathan
      Nov 20 at 0:54















    up vote
    1
    down vote













    You could define a generic function if you find yourself repeating the same things



    def prompt_for_valid_input(options):
    while True:
    print(f"You can choose one of {options}.")
    choice = input("Which would you choose? (or 'none' : ")
    if choice == "none" and "none" not in options:
    print("You didn't pick anything. That's fine.")
    return None
    elif choice in options:
    return choice
    else:
    print("That's not one of your options. Choose again. ")

    colors = ["red", "green", "white", "blue", "yellow"]
    color = prompt_for_valid_input(colors)
    if color is not None:
    print(f"You chose {color}! Have fun!")

    numbers = [1, 10, 100]
    num = prompt_for_valid_input(numbers)
    if num is not None:
    print(f"You chose {num}! Have fun!")


    So "without a while/for loop", not really. Without a sentinel variable, yes, if the conditions are simple enough.






    share|improve this answer





















    • Thanks for this, I like this idea. In my code, often times entering a certain input launches a function which itself might have more input validators. I like this idea and can probably implement it wisely in the right spots.
      – Jonathan
      Nov 20 at 0:54













    up vote
    1
    down vote










    up vote
    1
    down vote









    You could define a generic function if you find yourself repeating the same things



    def prompt_for_valid_input(options):
    while True:
    print(f"You can choose one of {options}.")
    choice = input("Which would you choose? (or 'none' : ")
    if choice == "none" and "none" not in options:
    print("You didn't pick anything. That's fine.")
    return None
    elif choice in options:
    return choice
    else:
    print("That's not one of your options. Choose again. ")

    colors = ["red", "green", "white", "blue", "yellow"]
    color = prompt_for_valid_input(colors)
    if color is not None:
    print(f"You chose {color}! Have fun!")

    numbers = [1, 10, 100]
    num = prompt_for_valid_input(numbers)
    if num is not None:
    print(f"You chose {num}! Have fun!")


    So "without a while/for loop", not really. Without a sentinel variable, yes, if the conditions are simple enough.






    share|improve this answer












    You could define a generic function if you find yourself repeating the same things



    def prompt_for_valid_input(options):
    while True:
    print(f"You can choose one of {options}.")
    choice = input("Which would you choose? (or 'none' : ")
    if choice == "none" and "none" not in options:
    print("You didn't pick anything. That's fine.")
    return None
    elif choice in options:
    return choice
    else:
    print("That's not one of your options. Choose again. ")

    colors = ["red", "green", "white", "blue", "yellow"]
    color = prompt_for_valid_input(colors)
    if color is not None:
    print(f"You chose {color}! Have fun!")

    numbers = [1, 10, 100]
    num = prompt_for_valid_input(numbers)
    if num is not None:
    print(f"You chose {num}! Have fun!")


    So "without a while/for loop", not really. Without a sentinel variable, yes, if the conditions are simple enough.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 20 at 0:45









    cricket_007

    77.8k1142108




    77.8k1142108












    • Thanks for this, I like this idea. In my code, often times entering a certain input launches a function which itself might have more input validators. I like this idea and can probably implement it wisely in the right spots.
      – Jonathan
      Nov 20 at 0:54


















    • Thanks for this, I like this idea. In my code, often times entering a certain input launches a function which itself might have more input validators. I like this idea and can probably implement it wisely in the right spots.
      – Jonathan
      Nov 20 at 0:54
















    Thanks for this, I like this idea. In my code, often times entering a certain input launches a function which itself might have more input validators. I like this idea and can probably implement it wisely in the right spots.
    – Jonathan
    Nov 20 at 0:54




    Thanks for this, I like this idea. In my code, often times entering a certain input launches a function which itself might have more input validators. I like this idea and can probably implement it wisely in the right spots.
    – Jonathan
    Nov 20 at 0:54












    up vote
    0
    down vote













    you can abstract it out to a generic validated input method



    def validated_input(prompt,validation_method,error_message):
    while True:
    result = input(prompt)
    if validation_method(result):
    return result
    print(error_message)


    choices = ['red','green','blue','none']
    validator = lambda test:test.lower().strip() in choices
    prompt = "Enter A Color(one of Red, Green, Blue, or None):"
    error_message = "Please enter a valid color or None!"

    print(validated_input(prompt,validator,error_message))


    its arguable whether this is "better"






    share|improve this answer





















    • Thanks Jordan. I see now how a function like this can actually help me a lot. Often my validations lead to a function, and sometimes those have more validations. I'll play with these kind of constructions and see if i can improve the code!
      – Jonathan
      Nov 20 at 0:56










    • *Joran! want to get your name right.
      – Jonathan
      Nov 20 at 1:12















    up vote
    0
    down vote













    you can abstract it out to a generic validated input method



    def validated_input(prompt,validation_method,error_message):
    while True:
    result = input(prompt)
    if validation_method(result):
    return result
    print(error_message)


    choices = ['red','green','blue','none']
    validator = lambda test:test.lower().strip() in choices
    prompt = "Enter A Color(one of Red, Green, Blue, or None):"
    error_message = "Please enter a valid color or None!"

    print(validated_input(prompt,validator,error_message))


    its arguable whether this is "better"






    share|improve this answer





















    • Thanks Jordan. I see now how a function like this can actually help me a lot. Often my validations lead to a function, and sometimes those have more validations. I'll play with these kind of constructions and see if i can improve the code!
      – Jonathan
      Nov 20 at 0:56










    • *Joran! want to get your name right.
      – Jonathan
      Nov 20 at 1:12













    up vote
    0
    down vote










    up vote
    0
    down vote









    you can abstract it out to a generic validated input method



    def validated_input(prompt,validation_method,error_message):
    while True:
    result = input(prompt)
    if validation_method(result):
    return result
    print(error_message)


    choices = ['red','green','blue','none']
    validator = lambda test:test.lower().strip() in choices
    prompt = "Enter A Color(one of Red, Green, Blue, or None):"
    error_message = "Please enter a valid color or None!"

    print(validated_input(prompt,validator,error_message))


    its arguable whether this is "better"






    share|improve this answer












    you can abstract it out to a generic validated input method



    def validated_input(prompt,validation_method,error_message):
    while True:
    result = input(prompt)
    if validation_method(result):
    return result
    print(error_message)


    choices = ['red','green','blue','none']
    validator = lambda test:test.lower().strip() in choices
    prompt = "Enter A Color(one of Red, Green, Blue, or None):"
    error_message = "Please enter a valid color or None!"

    print(validated_input(prompt,validator,error_message))


    its arguable whether this is "better"







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 20 at 0:45









    Joran Beasley

    71.7k676116




    71.7k676116












    • Thanks Jordan. I see now how a function like this can actually help me a lot. Often my validations lead to a function, and sometimes those have more validations. I'll play with these kind of constructions and see if i can improve the code!
      – Jonathan
      Nov 20 at 0:56










    • *Joran! want to get your name right.
      – Jonathan
      Nov 20 at 1:12


















    • Thanks Jordan. I see now how a function like this can actually help me a lot. Often my validations lead to a function, and sometimes those have more validations. I'll play with these kind of constructions and see if i can improve the code!
      – Jonathan
      Nov 20 at 0:56










    • *Joran! want to get your name right.
      – Jonathan
      Nov 20 at 1:12
















    Thanks Jordan. I see now how a function like this can actually help me a lot. Often my validations lead to a function, and sometimes those have more validations. I'll play with these kind of constructions and see if i can improve the code!
    – Jonathan
    Nov 20 at 0:56




    Thanks Jordan. I see now how a function like this can actually help me a lot. Often my validations lead to a function, and sometimes those have more validations. I'll play with these kind of constructions and see if i can improve the code!
    – Jonathan
    Nov 20 at 0:56












    *Joran! want to get your name right.
    – Jonathan
    Nov 20 at 1:12




    *Joran! want to get your name right.
    – Jonathan
    Nov 20 at 1:12










    up vote
    0
    down vote













    Usually how you wrote your code is considered pretty "normal" and straightforward which is good. The issue is that you would want the looping part of your code to repeat till it has met its expectation. So a conditional looping event is necessary. If you really want you can simplify it a little by making a break statement for example:



    x = 0
    while True:
    if x == 12:
    break;
    else:
    x = x + 1
    print(x)


    This will create a infinite loop until the condition you are looking for is met and then it will break out of the loop. Make sure you have your escape condition though.






    share|improve this answer

























      up vote
      0
      down vote













      Usually how you wrote your code is considered pretty "normal" and straightforward which is good. The issue is that you would want the looping part of your code to repeat till it has met its expectation. So a conditional looping event is necessary. If you really want you can simplify it a little by making a break statement for example:



      x = 0
      while True:
      if x == 12:
      break;
      else:
      x = x + 1
      print(x)


      This will create a infinite loop until the condition you are looking for is met and then it will break out of the loop. Make sure you have your escape condition though.






      share|improve this answer























        up vote
        0
        down vote










        up vote
        0
        down vote









        Usually how you wrote your code is considered pretty "normal" and straightforward which is good. The issue is that you would want the looping part of your code to repeat till it has met its expectation. So a conditional looping event is necessary. If you really want you can simplify it a little by making a break statement for example:



        x = 0
        while True:
        if x == 12:
        break;
        else:
        x = x + 1
        print(x)


        This will create a infinite loop until the condition you are looking for is met and then it will break out of the loop. Make sure you have your escape condition though.






        share|improve this answer












        Usually how you wrote your code is considered pretty "normal" and straightforward which is good. The issue is that you would want the looping part of your code to repeat till it has met its expectation. So a conditional looping event is necessary. If you really want you can simplify it a little by making a break statement for example:



        x = 0
        while True:
        if x == 12:
        break;
        else:
        x = x + 1
        print(x)


        This will create a infinite loop until the condition you are looking for is met and then it will break out of the loop. Make sure you have your escape condition though.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 20 at 1:24









        Jay Patel

        261




        261






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384614%2fis-there-a-better-way-to-evaluate-user-inputs-without-a-for-loop-and-changing%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Feedback on college project

            Futebolista

            Albești (Vaslui)