Functional approach or "look mum no loops!":
from itertools import chain, repeat
prompts = chain[["Enter a number: "], repeat["Not a number! Try again: "]]
replies = map[input, prompts]
valid_response = next[filter[str.isdigit, replies]]
print[valid_response]
Enter a number: a
Not a number! Try again: b
Not a number! Try again: 1
1
or if you want to have a "bad input" message separated from an input prompt as in other answers:
prompt_msg = "Enter a number: "
bad_input_msg = "Sorry, I didn't understand that."
prompts = chain[[prompt_msg], repeat['\n'.join[[bad_input_msg, prompt_msg]]]]
replies = map[input, prompts]
valid_response = next[filter[str.isdigit, replies]]
print[valid_response]
Enter a number: a
Sorry, I didn't understand that.
Enter a number: b
Sorry, I didn't understand that.
Enter a number: 1
1
How does it work?
This combination ofprompts = chain[["Enter a number: "], repeat["Not a number! Try again: "]]
itertools.chain
anditertools.repeat
will create an iterator which will yield strings"Enter a number: "
once, and"Not a number! Try again: "
an infinite number of times:for prompt in prompts: print[prompt]
Enter a number: Not a number! Try again: Not a number! Try again: Not a number! Try again: # ... and so on
replies = map[input, prompts]
- heremap
will apply all theprompts
strings from the previous step to theinput
function. E.g.:for reply in replies: print[reply]
Enter a number: a a Not a number! Try again: 1 1 Not a number! Try again: it doesn't care now it doesn't care now # and so on...
- We use
filter
andstr.isdigit
to filter out those strings that contain only digits:only_digits = filter[str.isdigit, replies] for reply in only_digits: print[reply]
And to get only the first digits-only string we useEnter a number: a Not a number! Try again: 1 1 Not a number! Try again: 2 2 Not a number! Try again: b Not a number! Try again: # and so on...
next
.
Other validation rules:
String methods: Of course you can use other string methods like
str.isalpha
to get only alphabetic strings, orstr.isupper
to get only uppercase. See docs for the full list.Membership testing:
There are several different ways to perform it. One of them is by using__contains__
method:from itertools import chain, repeat fruits = {'apple', 'orange', 'peach'} prompts = chain[["Enter a fruit: "], repeat["I don't know this one! Try again: "]] replies = map[input, prompts] valid_response = next[filter[fruits.__contains__, replies]] print[valid_response]
Enter a fruit: 1 I don't know this one! Try again: foo I don't know this one! Try again: apple apple
Numbers comparison:
There are useful comparison methods which we can use here. For example, for__lt__
[