Pedirle al usuario una entrada hasta que dé una respuesta válida
Estoy escribiendo un programa que acepta una entrada del usuario.
#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.")
El programa funciona como se esperaba siempre que el usuario ingrese datos significativos.
C:\Python\Projects> canyouvote.py
Please enter your age: 23
You are able to vote in the United States!
Pero falla si el usuario ingresa datos no válidos:
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'
En lugar de fallar, me gustaría que el programa volviera a solicitar la entrada. Me gusta esto:
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!
¿Cómo puedo hacer que el programa solicite entradas válidas en lugar de fallar cuando se ingresan datos sin sentido?
¿Cómo puedo rechazar valores como -1
, que es válido int
, pero sin sentido en este contexto?
Respuestas
La forma más sencilla de lograr esto es poner el input
método en un ciclo while. Úselo continue
cuando reciba una mala entrada y break
salga del circuito cuando esté satisfecho.
Cuándo su entrada podría generar una excepción
Utilice try
yexcept
para detectar cuándo el usuario ingresa datos que no se pueden analizar.
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.")
Implementación de sus propias reglas de validación
Si desea rechazar valores que Python puede analizar correctamente, puede agregar su propia lógica de validación.
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
Combinando el manejo de excepciones y la validación personalizada
Ambas técnicas anteriores se pueden combinar en un ciclo.
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.")
Encapsulando todo en una función
Si necesita pedirle a su usuario muchos valores diferentes, podría ser útil poner este código en una función, para que no tenga que volver a escribirlo cada vez.
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: ")
Poniendolo todo junto
Puede ampliar esta idea para hacer una función de entrada muy genérica:
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
Con usos como:
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
Errores comunes y por qué debería evitarlos
El uso redundante de input
declaraciones redundantes
Este método funciona, pero generalmente se considera de mal estilo:
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): ")
Puede parecer atractivo al principio porque es más corto que el while True
método, pero viola el principio de desarrollo de software de Don't Repeat Yourself . Esto aumenta la probabilidad de errores en su sistema. ¿Qué sucede si desea retroceder a 2.7 cambiando input
a raw_input
, pero accidentalmente cambia solo el primero de input
arriba? Es SyntaxError
simplemente esperar a que suceda.
La recursividad volará tu pila
Si acaba de aprender sobre la recursividad, es posible que tenga la tentación de usarla get_non_negative_int
para poder deshacerse del ciclo 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
Esto parece funcionar bien la mayor parte del tiempo, pero si el usuario ingresa datos no válidos suficientes veces, el script terminará con un RuntimeError: maximum recursion depth exceeded
. Puede pensar que "ningún tonto cometería 1000 errores seguidos", ¡pero está subestimando el ingenio de los tontos!
¿Por qué haría un while True
y luego saldría de este ciclo mientras que también puede poner sus requisitos en la declaración while, ya que todo lo que quiere es detenerse una vez que tenga la edad?
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.")
Esto resultaría en lo siguiente:
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.
esto funcionará ya que la edad nunca tendrá un valor que no tenga sentido y el código sigue la lógica de su "proceso comercial"
Aunque la respuesta aceptada es asombrosa. También me gustaría compartir un truco rápido para este problema. (Esto también soluciona el problema de la edad negativa).
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: ")))
PD: este código es para python 3.x.
Enfoque funcional o "¡ mira mamá sin bucles! "
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
o si desea tener un mensaje de "entrada incorrecta" separado de una solicitud de entrada como en otras respuestas:
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
¿Como funciona?
-
Esta combinación deprompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
itertools.chain
yitertools.repeat
creará un iterador que producirá cadenas"Enter a number: "
una vez y"Not a number! Try again: "
un número infinito de veces: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)
- aquímap
se aplicarán todas lasprompts
cadenas del paso anterior a lainput
función. P.ej: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...
- Usamos
filter
ystr.isdigit
para filtrar aquellas cadenas que contienen solo dígitos:only_digits = filter(str.isdigit, replies) for reply in only_digits: print(reply)
Y para obtener solo la primera cadena de dígitos que usamosEnter 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
.
Otras reglas de validación:
Métodos de cadena: por supuesto, puede usar otros métodos de cadena, como
str.isalpha
obtener solo cadenas alfabéticas ostr.isupper
solo mayúsculas. Consulte los documentos para obtener la lista completa.Prueba de membresía:
hay varias formas diferentes de realizarla. Uno de ellos es mediante el__contains__
método: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
Comparación de números:
existen métodos de comparación útiles que podemos utilizar aquí. Por ejemplo, para__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
O, si no le gusta usar métodos dunder (dunder = doble subrayado), siempre puede definir su propia función, o usar las del
operator
módulo.Existencia de ruta:
Aquí se puede usar lapathlib
biblioteca y suPath.exists
método: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
Limitación del número de intentos:
Si no desea torturar a un usuario preguntándole algo una cantidad infinita de veces, puede especificar un límite en una llamada de itertools.repeat
. Esto se puede combinar con proporcionar un valor predeterminado a la next
función:
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!
Procesamiento previo de datos de entrada:
A veces no queremos rechazar una entrada si el usuario la proporcionó accidentalmente EN MAYÚSCULAS o con un espacio al principio o al final de la cadena. Para tener en cuenta estos simples errores, podemos preprocesar los datos de entrada aplicando métodos str.lower
y str.strip
. Por ejemplo, para el caso de pruebas de membresía, el código se verá así:
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
En el caso de que tenga muchas funciones para usar para el preprocesamiento, podría ser más fácil usar una función que realiza una composición de función . Por ejemplo, usando el de aquí :
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
Combinando reglas de validación:
Para un caso simple, por ejemplo, cuando el programa pide una edad entre 1 y 120, se puede simplemente agregar otra 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)
Pero en el caso de que haya muchas reglas, es mejor implementar una función que realice una conjunción lógica . En el siguiente ejemplo, usaré uno listo de aquí :
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
Desafortunadamente, si alguien necesita un mensaje personalizado para cada caso fallido, me temo que no existe una forma bastante funcional. O, al menos, no pude encontrar uno.
Entonces, estaba jugando con algo similar a esto recientemente, y se me ocurrió la siguiente solución, que usa una forma de obtener información que rechaza la basura, incluso antes de que se verifique de manera lógica.
read_single_keypress()
cortesía 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()
Puede encontrar el módulo completo aquí .
Ejemplo:
$ ./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!
$ _
Tenga en cuenta que la naturaleza de esta implementación es que cierra stdin tan pronto como se lee algo que no es un dígito. No presioné Enter después a
, pero necesitaba hacerlo después de los números.
Puede fusionar esto con la thismany()
función en el mismo módulo para permitir solo, digamos, tres dígitos.
Usando Click :
Click es una biblioteca para interfaces de línea de comandos y proporciona funcionalidad para solicitar una respuesta válida de un usuario.
Ejemplo 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
Observe cómo convirtió el valor de la cadena en un flotante automáticamente.
Verificando si un valor está dentro de un rango:
Se proporcionan diferentes tipos personalizados . Para obtener un número en un rango específico, podemos usar 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
También podemos especificar solo uno de los límites, min
o 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
Prueba de membresía:
Usando click.Choice
tipo. De forma predeterminada, esta verificación distingue entre mayúsculas y minúsculas.
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
Trabajar con rutas y archivos:
Usando un click.Path
tipo podemos verificar las rutas existentes y también resolverlas:
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 lectura y escritura de archivos se puede realizar mediante 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!
Otros ejemplos:
Confirmación de contraseña:
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
Valores predeterminados:
En este caso, simplemente presionar Enter(o cualquier tecla que use) sin ingresar un valor, le dará uno predeterminado:
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."
Sobre la base de las excelentes sugerencias de Daniel Q y Patrick Artner, aquí hay una solución aún más generalizada.
# 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)
Opté por declaraciones explícitas if
y en raise
lugar de una assert
, porque la verificación de afirmaciones puede estar desactivada, mientras que la validación siempre debe estar activada para proporcionar solidez.
Esto puede usarse para obtener diferentes tipos de entrada, con diferentes condiciones de validación. Por ejemplo:
# 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!"})
O, para responder a la pregunta original:
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.")
Prueba este: -
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')
Sí, llego 6 años tarde desde el 🎉, pero esta pregunta merece una respuesta más actualizada.
Separación de intereses
Soy un gran fanático de la filosofía Unix "Haz una cosa y hazla bien" . En este tipo de problema, es una mejor práctica dividir el problema en
- Pregunte la entrada con
get_input
hasta que la entrada esté bien. - Validar en
validator
función. Puede escribir diferentes validadores para diferentes consultas de entrada.
Pidiendo aportes
Se puede mantener tan simple como (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)
Ejemplo
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'
Python 3.8+ Nota
En Python 3.8+, podría usar el operador de morsa
def get_input(prompt, validator, on_validationerror):
while not validator(value := input(prompt)):
print(on_validationerror)
return value
Si bien un bloque try
/ except
funcionará, una forma mucho más rápida y limpia de realizar esta tarea sería usar 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.")
¡Buena pregunta! Puede probar el siguiente código para esto. =)
Este código usa ast.literal_eval () para encontrar el tipo de datos de input ( age
). Luego sigue el siguiente algoritmo:
Pídale al usuario que ingrese la suya
age
.1.1. Si
age
esfloat
oint
tipo de datos:
Compruebe si
age>=18
. Siage>=18
, imprima la salida adecuada y salga.Compruebe si
0<age<18
. Si0<age<18
, imprima la salida adecuada y salga.Si
age<=0
, pida al usuario que ingrese un número válido para la edad nuevamente ( es decir, vuelva al paso 1.)1.2. Si
age
no esfloat
oint
el tipo de datos, solicite al usuario que ingrese su edad nuevamente ( es decir, vuelva al paso 1.)
Aquí está el código.
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.")
Siempre puede aplicar una lógica if-else simple y agregar una if
lógica más a su código junto con un for
bucle.
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
Este será un baño infinito y se le pedirá que ingrese la edad, indefinidamente.
El siguiente código puede ayudar.
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 desea tener el máximo de intentos, diga 3, use el siguiente código
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='')
Nota: esto usa recursividad.
Use try-except para manejar el error y repítalo nuevamente:
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")