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












4















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 '18 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 '18 at 0:48
















4















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 '18 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 '18 at 0:48














4












4








4








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 '18 at 0:39









cricket_007

80k1142110




80k1142110










asked Nov 20 '18 at 0:37









JonathanJonathan

314




314








  • 3





    this looks reasonable ...

    – Joran Beasley
    Nov 20 '18 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 '18 at 0:48














  • 3





    this looks reasonable ...

    – Joran Beasley
    Nov 20 '18 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 '18 at 0:48








3




3





this looks reasonable ...

– Joran Beasley
Nov 20 '18 at 0:40





this looks reasonable ...

– Joran Beasley
Nov 20 '18 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 '18 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 '18 at 0:48












3 Answers
3






active

oldest

votes


















1














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 '18 at 0:54



















0














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 '18 at 0:56











  • *Joran! want to get your name right.

    – Jonathan
    Nov 20 '18 at 1:12



















0














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',
    autoActivateHeartbeat: false,
    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









    1














    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 '18 at 0:54
















    1














    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 '18 at 0:54














    1












    1








    1







    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 '18 at 0:45









    cricket_007cricket_007

    80k1142110




    80k1142110













    • 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 '18 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 '18 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 '18 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 '18 at 0:54













    0














    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 '18 at 0:56











    • *Joran! want to get your name right.

      – Jonathan
      Nov 20 '18 at 1:12
















    0














    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 '18 at 0:56











    • *Joran! want to get your name right.

      – Jonathan
      Nov 20 '18 at 1:12














    0












    0








    0







    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 '18 at 0:45









    Joran BeasleyJoran Beasley

    72.5k678118




    72.5k678118













    • 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 '18 at 0:56











    • *Joran! want to get your name right.

      – Jonathan
      Nov 20 '18 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 '18 at 0:56











    • *Joran! want to get your name right.

      – Jonathan
      Nov 20 '18 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 '18 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 '18 at 0:56













    *Joran! want to get your name right.

    – Jonathan
    Nov 20 '18 at 1:12





    *Joran! want to get your name right.

    – Jonathan
    Nov 20 '18 at 1:12











    0














    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




























      0














      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


























        0












        0








        0







        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 '18 at 1:24









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




            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

            Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

            Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

            A Topological Invariant for $pi_3(U(n))$