0

I am seeking assistance on properly using the following 3 while loops:

while choice is None:  ...
while not isinstance (choice, int):  ...
while int(choice) not in range(0,1):  ...

Something like this perhaps:

while choice is None and not isinstance (choice, int) and int(choice) not in range(0,1):
    print("Invalid option!")
    choice = input("Choose key: ")

How would I properly nest this?

choice = None
choice = input("Choose key: ")

while choice is None:
    choice = input("Choose key: ")

while not isinstance (choice, int):
    print("choice is an integer and I equal 0 or 1")
    print("Also if I am None or not an int, I will loop until I meet I am")

while int(choice) not in range(0,1):
    choice = input("Choose key: ")
    choice = int(choice)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Evan
  • 25
  • 5
  • 1
    I'd prefer using recursion for things like this :) – Sasha Aug 10 '18 at 12:47
  • It's unclear what you want to happen. What is the purpose the of the while loop(s)? Are you trying to ask the user for input until they give a valid response? Please see [mcve] and describe the desired result. – Aran-Fey Aug 10 '18 at 12:47
  • Use `while True` and if-statements with `break`? That may be clearer than a series of while loops. – 9769953 Aug 10 '18 at 12:47
  • 1
    So is your aim to get a valid integer input? – N Chauhan Aug 10 '18 at 12:49
  • 1
    Note that `choice` will never be equal to `None`, except on the first line. – 9769953 Aug 10 '18 at 12:49
  • [Asking the user for input until they give a valid response](https://stackoverflow.com/q/23294658/953482) may be of interest to you. – Kevin Aug 10 '18 at 12:50
  • @Jaxi Recursion is the wrong choice for this kind of loop in Python, as it imposes an arbitrary upperbound and a performance penalty compared to a `while` loop. – chepner Aug 10 '18 at 12:53
  • Yes, I am trying to get a valid integer which matches an integer from range(0,1). Thanks for the for the links above! – Evan Aug 10 '18 at 13:03

5 Answers5

5

You can condense this nicely by moving everything into one loop:

while True:
    choice = input("Choose key: ")
    if choice in ("0", "1"):
        choice = int(choice)
        break
chris
  • 1,915
  • 2
  • 13
  • 18
  • 1
    That's an elegant solution! I hadn't considered just testing against a `"1", "0"` instead of converting. Neat. – N Chauhan Aug 10 '18 at 13:02
3

input returns a str object, period. It will never return None, it will never return an int. Just (try to) convert choice to an int, then check the resulting value, breaking only when a 0 or 1 is entered.

while True:
    choice = input("Choose key: ")
    try:
        choice = int(choice)
    except ValueError:
        continue
    if choice in (0, 1):
        break
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Thank you so, so much! I am new to programming. I was no expecting something so clean and elegant. Thank you chepner! – Evan Aug 10 '18 at 13:06
  • 1
    I would accept [@chris's answer](https://stackoverflow.com/a/51787013/1126841) instead, as it delays the call to `int` until you have an input you know won't raise an exception. – chepner Aug 10 '18 at 13:35
1

If you need an integer input...

while True:
    try:
        choice = int(input('Enter choice: '))
    except ValueError:
        print('Invalid choice')
    else:
        # add an if statement here to add another condition to test the int against before accepting input
        break
# .... do whatever next with you integer
N Chauhan
  • 3,407
  • 2
  • 7
  • 21
0

If I understand corrently this is less about nesting and more about ordering, right? How about:

In [10]: choice = None

In [11]: while (
...:     not choice or
...:     not choice.isdigit() or
...:     int(choice) not in range(0,2)
...: ):
...:     print("Invalid option!")
...:     choice = input("Choose key: ")
Bernd
  • 112
  • 7
0
choice = None
while choice not in range(0,1):
    choice = int(input("Choose key: "))

I don't know if that's what you were trying to do

Vex -
  • 19
  • 5
  • 1
    `isinstance()` won't raise an error, it will just return `False` – N Chauhan Aug 10 '18 at 13:00
  • 1
    Just as a side note, I don't recommend using `isinstance()` for type checking, as it is unpythonic. Following the `Easier to Ask for Forgiveness than Permission (EAFP)` motto, using a `try/except` block to attempt to convert to an integer is preferred. When coding, we assume we **can** do something, and if we can't, handle the exception appropriately. – N Chauhan Aug 10 '18 at 13:05
  • I don't know much yet about python and dev in general as I'm a beginner. I didn't know the right ways of using the try/except blocks, and wanted to use what OP used in his code for the `isinstance()`part. I'll keep that in mind next time, thank you for the advice :) – Vex - Aug 10 '18 at 13:11
  • 1
    Have a search for "EAFP" or "duck typing" if you're interested :) – N Chauhan Aug 10 '18 at 13:13