Demander à l'utilisateur une entrée jusqu'à ce qu'il donne une réponse valide
J'écris un programme qui accepte une entrée de l'utilisateur.
#note: Python 2.7 users should use `raw_input`, the equivalent of 3.X's `input`
age = int(input("Please enter your age: "))
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Le programme fonctionne comme prévu tant que l'utilisateur entre des données significatives.
C:\Python\Projects> canyouvote.py
Please enter your age: 23
You are able to vote in the United States!
Mais cela échoue si l'utilisateur entre des données invalides:
C:\Python\Projects> canyouvote.py
Please enter your age: dickety six
Traceback (most recent call last):
File "canyouvote.py", line 1, in <module>
age = int(input("Please enter your age: "))
ValueError: invalid literal for int() with base 10: 'dickety six'
Au lieu de planter, j'aimerais que le programme demande à nouveau l'entrée. Comme ça:
C:\Python\Projects> canyouvote.py
Please enter your age: dickety six
Sorry, I didn't understand that.
Please enter your age: 26
You are able to vote in the United States!
Comment puis-je faire en sorte que le programme demande des entrées valides au lieu de s'écraser lorsque des données non sensibles sont entrées?
Comment puis-je rejeter des valeurs comme -1
, qui est valide int
, mais absurde dans ce contexte?
Réponses
Le moyen le plus simple d'y parvenir est de placer la input
méthode dans une boucle while. À utiliser continue
lorsque vous obtenez une mauvaise entrée et break
hors de la boucle lorsque vous êtes satisfait.
Quand votre contribution pourrait soulever une exception
Utilisez try
etexcept
pour détecter lorsque l'utilisateur entre des données qui ne peuvent pas être analysées.
while True:
try:
# Note: Python 2.x users should use raw_input, the equivalent of 3.x's input
age = int(input("Please enter your age: "))
except ValueError:
print("Sorry, I didn't understand that.")
#better try again... Return to the start of the loop
continue
else:
#age was successfully parsed!
#we're ready to exit the loop.
break
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Mettre en œuvre vos propres règles de validation
Si vous souhaitez rejeter les valeurs que Python peut analyser avec succès, vous pouvez ajouter votre propre logique de validation.
while True:
data = input("Please enter a loud message (must be all caps): ")
if not data.isupper():
print("Sorry, your response was not loud enough.")
continue
else:
#we're happy with the value given.
#we're ready to exit the loop.
break
while True:
data = input("Pick an answer from A to D:")
if data.lower() not in ('a', 'b', 'c', 'd'):
print("Not an appropriate choice.")
else:
break
Combinaison de la gestion des exceptions et de la validation personnalisée
Les deux techniques ci-dessus peuvent être combinées en une seule boucle.
while True:
try:
age = int(input("Please enter your age: "))
except ValueError:
print("Sorry, I didn't understand that.")
continue
if age < 0:
print("Sorry, your response must not be negative.")
continue
else:
#age was successfully parsed, and we're happy with its value.
#we're ready to exit the loop.
break
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Tout encapsuler dans une fonction
Si vous avez besoin de demander à votre utilisateur un grand nombre de valeurs différentes, il peut être utile de mettre ce code dans une fonction afin de ne pas avoir à le retaper à chaque fois.
def get_non_negative_int(prompt):
while True:
try:
value = int(input(prompt))
except ValueError:
print("Sorry, I didn't understand that.")
continue
if value < 0:
print("Sorry, your response must not be negative.")
continue
else:
break
return value
age = get_non_negative_int("Please enter your age: ")
kids = get_non_negative_int("Please enter the number of children you have: ")
salary = get_non_negative_int("Please enter your yearly earnings, in dollars: ")
Mettre tous ensemble
Vous pouvez étendre cette idée pour créer une fonction d'entrée très générique:
def sanitised_input(prompt, type_=None, min_=None, max_=None, range_=None):
if min_ is not None and max_ is not None and max_ < min_:
raise ValueError("min_ must be less than or equal to max_.")
while True:
ui = input(prompt)
if type_ is not None:
try:
ui = type_(ui)
except ValueError:
print("Input type must be {0}.".format(type_.__name__))
continue
if max_ is not None and ui > max_:
print("Input must be less than or equal to {0}.".format(max_))
elif min_ is not None and ui < min_:
print("Input must be greater than or equal to {0}.".format(min_))
elif range_ is not None and ui not in range_:
if isinstance(range_, range):
template = "Input must be between {0.start} and {0.stop}."
print(template.format(range_))
else:
template = "Input must be {0}."
if len(range_) == 1:
print(template.format(*range_))
else:
expected = " or ".join((
", ".join(str(x) for x in range_[:-1]),
str(range_[-1])
))
print(template.format(expected))
else:
return ui
Avec des usages tels que:
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
Les pièges courants et pourquoi vous devriez les éviter
L'utilisation redondante d' input
instructions redondantes
Cette méthode fonctionne mais est généralement considérée comme un style médiocre:
data = input("Please enter a loud message (must be all caps): ")
while not data.isupper():
print("Sorry, your response was not loud enough.")
data = input("Please enter a loud message (must be all caps): ")
Cela peut sembler attrayant au départ car il est plus court que la while True
méthode, mais cela viole le principe de ne pas se répéter du développement logiciel. Cela augmente la probabilité de bogues dans votre système. Que faire si vous souhaitez effectuer un rétroportage vers 2.7 en passant input
à raw_input
, mais en ne modifiant accidentellement que le premier input
ci-dessus? C'est une SyntaxError
attente juste pour arriver.
La récursion fera exploser votre pile
Si vous venez d'apprendre la récursivité, vous pourriez être tenté de l'utiliser get_non_negative_int
pour vous débarrasser de la boucle while.
def get_non_negative_int(prompt):
try:
value = int(input(prompt))
except ValueError:
print("Sorry, I didn't understand that.")
return get_non_negative_int(prompt)
if value < 0:
print("Sorry, your response must not be negative.")
return get_non_negative_int(prompt)
else:
return value
Cela semble fonctionner correctement la plupart du temps, mais si l'utilisateur entre des données non valides suffisamment de fois, le script se terminera par un RuntimeError: maximum recursion depth exceeded
. Vous pensez peut-être "aucun imbécile ne ferait 1000 erreurs d'affilée", mais vous sous-estimez l'ingéniosité des imbéciles!
Pourquoi feriez-vous un while True
puis sortez de cette boucle alors que vous pouvez également simplement mettre vos exigences dans l'instruction while puisque tout ce que vous voulez, c'est arrêter une fois que vous avez l'âge?
age = None
while age is None:
input_value = input("Please enter your age: ")
try:
# try and convert the string input to a number
age = int(input_value)
except ValueError:
# tell the user off
print("{input} is not a number, please enter a number only".format(input=input_value))
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Cela entraînerait ce qui suit:
Please enter your age: *potato*
potato is not a number, please enter a number only
Please enter your age: *5*
You are not able to vote in the United States.
cela fonctionnera car l'âge n'aura jamais une valeur qui n'aura aucun sens et le code suit la logique de votre "processus métier"
Bien que la réponse acceptée soit incroyable. Je voudrais également partager un hack rapide pour ce problème. (Cela règle également le problème d'âge négatif.)
f=lambda age: (age.isdigit() and ((int(age)>=18 and "Can vote" ) or "Cannot vote")) or \
f(input("invalid input. Try again\nPlease enter your age: "))
print(f(input("Please enter your age: ")))
PS Ce code est pour python 3.x.
Approche fonctionnelle ou " 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
ou si vous voulez avoir un message de "mauvaise entrée" séparé d'une invite de saisie comme dans les autres réponses:
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
Comment ça marche?
-
Cette combinaison deprompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
itertools.chain
etitertools.repeat
créera un itérateur qui produira des chaînes"Enter a number: "
une fois, et"Not a number! Try again: "
un nombre infini de fois: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)
- icimap
appliquera toutes lesprompts
chaînes de l'étape précédente à lainput
fonction. Par exemple: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...
- Nous utilisons
filter
etstr.isdigit
pour filtrer les chaînes qui ne contiennent que des chiffres:only_digits = filter(str.isdigit, replies) for reply in only_digits: print(reply)
Et pour obtenir uniquement la première chaîne de chiffres que nous utilisonsEnter 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
.
Autres règles de validation:
Méthodes de chaîne: bien sûr, vous pouvez utiliser d'autres méthodes de chaîne comme
str.isalpha
pour obtenir uniquement des chaînes alphabétiques oustr.isupper
pour obtenir uniquement des majuscules. Voir la documentation pour la liste complète.Test d'adhésion:
il existe plusieurs façons de le réaliser. L'un d'eux consiste à utiliser la__contains__
méthode: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
Comparaison des nombres:
Il existe des méthodes de comparaison utiles que nous pouvons utiliser ici. Par exemple, pour__lt__
(<
):from itertools import chain, repeat prompts = chain(["Enter a positive number:"], repeat("I need a positive number! Try again:")) replies = map(input, prompts) numeric_strings = filter(str.isnumeric, replies) numbers = map(float, numeric_strings) is_positive = (0.).__lt__ valid_response = next(filter(is_positive, numbers)) print(valid_response)
Enter a positive number: a I need a positive number! Try again: -5 I need a positive number! Try again: 0 I need a positive number! Try again: 5 5.0
Ou, si vous n'aimez pas utiliser les méthodes dunder (dunder = double-underscore), vous pouvez toujours définir votre propre fonction, ou utiliser celles du
operator
module.Existence de chemin:
Ici, on peut utiliser lapathlib
bibliothèque et saPath.exists
méthode:from itertools import chain, repeat from pathlib import Path prompts = chain(["Enter a path: "], repeat("This path doesn't exist! Try again: ")) replies = map(input, prompts) paths = map(Path, replies) valid_response = next(filter(Path.exists, paths)) print(valid_response)
Enter a path: a b c This path doesn't exist! Try again: 1 This path doesn't exist! Try again: existing_file.txt existing_file.txt
Limitation du nombre d'essais:
Si vous ne voulez pas torturer un utilisateur en lui demandant quelque chose un nombre infini de fois, vous pouvez spécifier une limite dans un appel de itertools.repeat
. Cela peut être combiné avec la fourniture d'une valeur par défaut à la next
fonction:
from itertools import chain, repeat
prompts = chain(["Enter a number:"], repeat("Not a number! Try again:", 2))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies), None)
print("You've failed miserably!" if valid_response is None else 'Well done!')
Enter a number: a
Not a number! Try again: b
Not a number! Try again: c
You've failed miserably!
Prétraitement des données d'entrée:
Parfois, nous ne voulons pas rejeter une entrée si l'utilisateur l'a accidentellement fournie EN MAJUSCULES ou avec un espace au début ou à la fin de la chaîne. Pour prendre en compte ces simples erreurs, nous pouvons prétraiter les données d'entrée en appliquant des méthodes str.lower
et str.strip
. Par exemple, dans le cas du test d'adhésion, le code ressemblera à ceci:
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)
lowercased_replies = map(str.lower, replies)
stripped_replies = map(str.strip, lowercased_replies)
valid_response = next(filter(fruits.__contains__, stripped_replies))
print(valid_response)
Enter a fruit: duck
I don't know this one! Try again: Orange
orange
Dans le cas où vous avez de nombreuses fonctions à utiliser pour le prétraitement, il peut être plus facile d'utiliser une fonction exécutant une composition de fonctions . Par exemple, en utilisant celui d' ici :
from itertools import chain, repeat
from lz.functional import compose
fruits = {'apple', 'orange', 'peach'}
prompts = chain(["Enter a fruit: "], repeat("I don't know this one! Try again: "))
replies = map(input, prompts)
process = compose(str.strip, str.lower) # you can add more functions here
processed_replies = map(process, replies)
valid_response = next(filter(fruits.__contains__, processed_replies))
print(valid_response)
Enter a fruit: potato
I don't know this one! Try again: PEACH
peach
Combinaison des règles de validation:
Pour un cas simple, par exemple, lorsque le programme demande un âge entre 1 et 120 ans, on peut simplement en ajouter un autre filter
:
from itertools import chain, repeat
prompt_msg = "Enter your age (1-120): "
bad_input_msg = "Wrong input."
prompts = chain([prompt_msg], repeat('\n'.join([bad_input_msg, prompt_msg])))
replies = map(input, prompts)
numeric_replies = filter(str.isdigit, replies)
ages = map(int, numeric_replies)
positive_ages = filter((0).__lt__, ages)
not_too_big_ages = filter((120).__ge__, positive_ages)
valid_response = next(not_too_big_ages)
print(valid_response)
Mais dans le cas où il existe de nombreuses règles, il est préférable d'implémenter une fonction réalisant une conjonction logique . Dans l'exemple suivant, j'utiliserai un prêt à partir d' ici :
from functools import partial
from itertools import chain, repeat
from lz.logical import conjoin
def is_one_letter(string: str) -> bool:
return len(string) == 1
rules = [str.isalpha, str.isupper, is_one_letter, 'C'.__le__, 'P'.__ge__]
prompt_msg = "Enter a letter (C-P): "
bad_input_msg = "Wrong input."
prompts = chain([prompt_msg], repeat('\n'.join([bad_input_msg, prompt_msg])))
replies = map(input, prompts)
valid_response = next(filter(conjoin(*rules), replies))
print(valid_response)
Enter a letter (C-P): 5
Wrong input.
Enter a letter (C-P): f
Wrong input.
Enter a letter (C-P): CDE
Wrong input.
Enter a letter (C-P): Q
Wrong input.
Enter a letter (C-P): N
N
Malheureusement, si quelqu'un a besoin d'un message personnalisé pour chaque cas échoué, alors, j'ai peur, il n'y a pas de moyen très fonctionnel. Ou du moins, je n'en ai pas trouvé.
Donc, je déconnais quelque chose de similaire récemment, et j'ai trouvé la solution suivante, qui utilise un moyen d'obtenir des entrées qui rejettent les indésirables, avant même qu'elles ne soient vérifiées de manière logique.
read_single_keypress()
avec la permission de https://stackoverflow.com/a/6599441/4532996
def read_single_keypress() -> str:
"""Waits for a single keypress on stdin.
-- from :: https://stackoverflow.com/a/6599441/4532996
"""
import termios, fcntl, sys, os
fd = sys.stdin.fileno()
# save old state
flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
attrs_save = termios.tcgetattr(fd)
# make raw - the way to do this comes from the termios(3) man page.
attrs = list(attrs_save) # copy the stored version to update
# iflag
attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
| termios.ISTRIP | termios.INLCR | termios. IGNCR
| termios.ICRNL | termios.IXON )
# oflag
attrs[1] &= ~termios.OPOST
# cflag
attrs[2] &= ~(termios.CSIZE | termios. PARENB)
attrs[2] |= termios.CS8
# lflag
attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
| termios.ISIG | termios.IEXTEN)
termios.tcsetattr(fd, termios.TCSANOW, attrs)
# turn off non-blocking
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
# read a single keystroke
try:
ret = sys.stdin.read(1) # returns a single character
except KeyboardInterrupt:
ret = 0
finally:
# restore old state
termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
return ret
def until_not_multi(chars) -> str:
"""read stdin until !(chars)"""
import sys
chars = list(chars)
y = ""
sys.stdout.flush()
while True:
i = read_single_keypress()
_ = sys.stdout.write(i)
sys.stdout.flush()
if i not in chars:
break
y += i
return y
def _can_you_vote() -> str:
"""a practical example:
test if a user can vote based purely on keypresses"""
print("can you vote? age : ", end="")
x = int("0" + until_not_multi("0123456789"))
if not x:
print("\nsorry, age can only consist of digits.")
return
print("your age is", x, "\nYou can vote!" if x >= 18 else "Sorry! you can't vote")
_can_you_vote()
Vous pouvez trouver le module complet ici .
Exemple:
$ ./input_constrain.py
can you vote? age : a
sorry, age can only consist of digits.
$ ./input_constrain.py
can you vote? age : 23<RETURN>
your age is 23
You can vote!
$ _
Notez que la nature de cette implémentation est qu'elle ferme stdin dès que quelque chose qui n'est pas un chiffre est lu. Je n'ai pas appuyé sur Entrée après a
, mais je devais après les chiffres.
Vous pouvez fusionner cela avec la thismany()
fonction dans le même module pour n'autoriser que, disons, trois chiffres.
En utilisant Click :
Click est une bibliothèque pour les interfaces de ligne de commande et fournit des fonctionnalités pour demander une réponse valide à un utilisateur.
Exemple simple:
import click
number = click.prompt('Please enter a number', type=float)
print(number)
Please enter a number:
a
Error: a is not a valid floating point value
Please enter a number:
10
10.0
Notez comment il a converti automatiquement la valeur de chaîne en flottant.
Vérifier si une valeur est comprise dans une plage:
Il existe différents types personnalisés fournis. Pour obtenir un nombre dans une plage spécifique, nous pouvons utiliser IntRange
:
age = click.prompt("What's your age?", type=click.IntRange(1, 120))
print(age)
What's your age?:
a
Error: a is not a valid integer
What's your age?:
0
Error: 0 is not in the valid range of 1 to 120.
What's your age?:
5
5
Nous pouvons également spécifier une seule des limites, min
ou max
:
age = click.prompt("What's your age?", type=click.IntRange(min=14))
print(age)
What's your age?:
0
Error: 0 is smaller than the minimum valid value 14.
What's your age?:
18
18
Test d'adhésion:
Utilisation du click.Choice
type. Par défaut, cette vérification est sensible à la casse.
choices = {'apple', 'orange', 'peach'}
choice = click.prompt('Provide a fruit', type=click.Choice(choices, case_sensitive=False))
print(choice)
Provide a fruit (apple, peach, orange):
banana
Error: invalid choice: banana. (choose from apple, peach, orange)
Provide a fruit (apple, peach, orange):
OrAnGe
orange
Travailler avec des chemins et des fichiers:
En utilisant un click.Path
type, nous pouvons vérifier les chemins existants et les résoudre également:
path = click.prompt('Provide path', type=click.Path(exists=True, resolve_path=True))
print(path)
Provide path:
nonexistent
Error: Path "nonexistent" does not exist.
Provide path:
existing_folder
'/path/to/existing_folder
La lecture et l'écriture de fichiers peuvent être effectuées par click.File
:
file = click.prompt('In which file to write data?', type=click.File('w'))
with file.open():
file.write('Hello!')
# More info about `lazy=True` at:
# https://click.palletsprojects.com/en/7.x/arguments/#file-opening-safety
file = click.prompt('Which file you wanna read?', type=click.File(lazy=True))
with file.open():
print(file.read())
In which file to write data?:
# <-- provided an empty string, which is an illegal name for a file
In which file to write data?:
some_file.txt
Which file you wanna read?:
nonexistent.txt
Error: Could not open file: nonexistent.txt: No such file or directory
Which file you wanna read?:
some_file.txt
Hello!
Autres exemples:
Confirmation mot de passe:
password = click.prompt('Enter password', hide_input=True, confirmation_prompt=True)
print(password)
Enter password:
······
Repeat for confirmation:
·
Error: the two entered values do not match
Enter password:
······
Repeat for confirmation:
······
qwerty
Les valeurs par défaut:
Dans ce cas, appuyez simplement sur Enter(ou sur n'importe quelle touche que vous utilisez) sans entrer de valeur, vous en donnera une par défaut:
number = click.prompt('Please enter a number', type=int, default=42)
print(number)
Please enter a number [42]:
a
Error: a is not a valid integer
Please enter a number [42]:
42
def validate_age(age):
if age >=0 :
return True
return False
while True:
try:
age = int(raw_input("Please enter your age:"))
if validate_age(age): break
except ValueError:
print "Error: Invalid age."
S'appuyant sur les excellentes suggestions de Daniel Q et Patrick Artner, voici une solution encore plus généralisée.
# Assuming Python3
import sys
class ValidationError(ValueError): # thanks Patrick Artner
pass
def validate_input(prompt, cast=str, cond=(lambda x: True), onerror=None):
if onerror==None: onerror = {}
while True:
try:
data = cast(input(prompt))
if not cond(data): raise ValidationError
return data
except tuple(onerror.keys()) as e: # thanks Daniel Q
print(onerror[type(e)], file=sys.stderr)
J'ai opté pour les instructions explicites if
et raise
au lieu de an assert
, car la vérification des assertions peut être désactivée, alors que la validation doit toujours être activée pour assurer la robustesse.
Cela peut être utilisé pour obtenir différents types d'entrée, avec différentes conditions de validation. Par exemple:
# No validation, equivalent to simple input:
anystr = validate_input("Enter any string: ")
# Get a string containing only letters:
letters = validate_input("Enter letters: ",
cond=str.isalpha,
onerror={ValidationError: "Only letters, please!"})
# Get a float in [0, 100]:
percentage = validate_input("Percentage? ",
cast=float, cond=lambda x: 0.0<=x<=100.0,
onerror={ValidationError: "Must be between 0 and 100!",
ValueError: "Not a number!"})
Ou, pour répondre à la question initiale:
age = validate_input("Please enter your age: ",
cast=int, cond=lambda a:0<=a<150,
onerror={ValidationError: "Enter a plausible age, please!",
ValueError: "Enter an integer, please!"})
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Essaye celui-là:-
def takeInput(required):
print 'ooo or OOO to exit'
ans = raw_input('Enter: ')
if not ans:
print "You entered nothing...!"
return takeInput(required)
## FOR Exit ##
elif ans in ['ooo', 'OOO']:
print "Closing instance."
exit()
else:
if ans.isdigit():
current = 'int'
elif set('[~!@#$%^&*()_+{}":/\']+$').intersection(ans):
current = 'other'
elif isinstance(ans,basestring):
current = 'str'
else:
current = 'none'
if required == current :
return ans
else:
return takeInput(required)
## pass the value in which type you want [str/int/special character(as other )]
print "input: ", takeInput('str')
Ouais, j'ai 6 ans de retard par rapport au 🎉 mais cette question mérite une réponse plus à jour.
Séparation des préoccupations
Je suis un grand fan de la philosophie Unix "Faites une chose et faites-la bien" . Dans ce type de problème, il est préférable de diviser le problème en
- Demandez l'entrée avec
get_input
jusqu'à ce que l'entrée soit correcte. - Validez en
validator
fonction. Vous pouvez écrire différents validateurs pour différentes requêtes d'entrée.
Demander une contribution
Il peut être aussi simple que (Python 3+)
def myvalidator(value):
try:
value = int(value)
except ValueError:
return False
return value >= 0
def get_input(prompt, validator, on_validationerror):
while True:
value = input(prompt)
if validator(value):
return value
print(on_validationerror)
Exemple
In [2]: get_input('Give a positive number: ', myvalidator, 'Please, try again')
Give a positive number: foobar
Please, try again
Give a positive number: -10
Please, try again
Give a positive number: 42
Out[2]: '42'
Remarque sur Python 3.8+
Dans Python 3.8+, vous pouvez utiliser l'opérateur morse
def get_input(prompt, validator, on_validationerror):
while not validator(value := input(prompt)):
print(on_validationerror)
return value
Bien qu'un bloc try
/ except
fonctionne, un moyen beaucoup plus rapide et plus propre d'accomplir cette tâche serait d'utiliser str.isdigit()
.
while True:
age = input("Please enter your age: ")
if age.isdigit():
age = int(age)
break
else:
print("Invalid number '{age}'. Try again.".format(age=age))
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Bonne question! Vous pouvez essayer le code suivant pour cela. =)
Ce code utilise ast.literal_eval () pour trouver le type de données de input ( age
). Ensuite, il suit l'algorithme suivant:
Demandez à l'utilisateur de le saisir
age
.1.1. Si
age
estfloat
ouint
type de données:
Vérifiez si
age>=18
. Siage>=18
, imprimez la sortie appropriée et quittez.Vérifiez si
0<age<18
. Si0<age<18
, imprimez la sortie appropriée et quittez.Si
age<=0
, demandez à l'utilisateur de saisir à nouveau un numéro valide pour l'âge, ( c'est -à- dire, revenez à l'étape 1.)1.2. Si ce
age
n'est pas le type de donnéesfloat
ouint
, demandez à l'utilisateur de saisir à nouveau son âge ( c'est -à- dire de revenir à l'étape 1.)
Voici le code.
from ast import literal_eval
''' This function is used to identify the data type of input data.'''
def input_type(input_data):
try:
return type(literal_eval(input_data))
except (ValueError, SyntaxError):
return str
flag = True
while(flag):
age = raw_input("Please enter your age: ")
if input_type(age)==float or input_type(age)==int:
if eval(age)>=18:
print("You are able to vote in the United States!")
flag = False
elif eval(age)>0 and eval(age)<18:
print("You are not able to vote in the United States.")
flag = False
else: print("Please enter a valid number as your age.")
else: print("Sorry, I didn't understand that.")
Vous pouvez toujours appliquer une logique if-else simple et ajouter une if
logique supplémentaire à votre code avec une for
boucle.
while True:
age = int(input("Please enter your age: "))
if (age >= 18) :
print("You are able to vote in the United States!")
if (age < 18) & (age > 0):
print("You are not able to vote in the United States.")
else:
print("Wrong characters, the input must be numeric")
continue
Ce sera un loo infini et on vous demandera d'entrer dans l'âge, indéfiniment.
Le code ci-dessous peut vous aider.
age=(lambda i,f: f(i,f))(input("Please enter your age: "),lambda i,f: i if i.isdigit() else f(input("Please enter your age: "),f))
print("You are able to vote in the united states" if int(age)>=18 else "You are not able to vote in the united states",end='')
Si vous voulez avoir un maximum d'essais, disons 3, utilisez le code ci-dessous
age=(lambda i,n,f: f(i,n,f))(input("Please enter your age: "),1,lambda i,n,f: i if i.isdigit() else (None if n==3 else f(input("Please enter your age: "),n+1,f)))
print("You are able to vote in the united states" if age and int(age)>=18 else "You are not able to vote in the united states",end='')
Remarque: cela utilise la récursivité.
Utilisez try-except pour gérer l'erreur et répétez-la à nouveau:
while True:
try:
age = int(input("Please enter your age: "))
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
except Exception as e:
print("please enter number")