Solicitando a entrada do usuário até que ele dê uma resposta válida
Estou escrevendo um programa que aceita uma entrada do usuário.
#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.")
O programa funciona conforme o esperado, desde que o usuário insira dados significativos.
C:\Python\Projects> canyouvote.py
Please enter your age: 23
You are able to vote in the United States!
Mas ele falha se o usuário inserir dados invá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'
Em vez de travar, gostaria que o programa solicitasse a entrada novamente. Como isso:
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!
Como posso fazer com que o programa solicite entradas válidas em vez de travar quando dados sem sentido são inseridos?
Como posso rejeitar valores como -1
, que é válido int
, mas sem sentido neste contexto?
Respostas
A maneira mais simples de fazer isso é colocar o input
método em um loop while. Use continue
quando você receber uma entrada ruim e break
saia do loop quando estiver satisfeito.
Quando sua opinião pode levantar uma exceção
Use try
eexcept
para detectar quando o usuário insere dados que não podem ser analisados.
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.")
Implementando suas próprias regras de validação
Se você deseja rejeitar valores que Python pode analisar com êxito, você pode adicionar sua própria lógica de validação.
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 tratamento de exceções e validação personalizada
Ambas as técnicas acima podem ser combinadas em um loop.
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 tudo em uma função
Se você precisar pedir ao usuário vários valores diferentes, pode ser útil colocar esse código em uma função, para que você não precise redigitá-lo todas as vezes.
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: ")
Juntando tudo
Você pode estender essa ideia para fazer uma função de entrada muito 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
Com uso como:
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
Armadilhas comuns e por que você deve evitá-las
O Uso Redundante de input
Declarações Redundantes
Este método funciona, mas geralmente é considerado um estilo pobre:
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): ")
Pode parecer atraente inicialmente porque é mais curto do que o while True
método, mas viola o princípio Don't Repeat Yourself do desenvolvimento de software. Isso aumenta a probabilidade de bugs em seu sistema. E se você quiser retroceder para 2.7 mudando input
para raw_input
, mas acidentalmente mudar apenas o primeiro input
acima? É SyntaxError
apenas uma espera para acontecer.
A recursão vai explodir sua pilha
Se você acabou de aprender sobre recursão, pode ficar tentado a usá-lo get_non_negative_int
para descartar o loop 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
Isso parece funcionar bem na maioria das vezes, mas se o usuário inserir dados inválidos muitas vezes, o script será encerrado com um RuntimeError: maximum recursion depth exceeded
. Você pode pensar "nenhum tolo cometeria 1000 erros consecutivos", mas está subestimando a engenhosidade dos tolos!
Por que você faria um while True
e depois sairia desse loop enquanto também pode simplesmente colocar seus requisitos na instrução while, já que tudo o que você quer é parar quando tiver a idade?
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.")
Isso resultaria no seguinte:
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.
isso vai funcionar desde a idade nunca terá um valor que não faça sentido e o código segue a lógica do seu "processo de negócios"
Embora a resposta aceita seja incrível. Eu também gostaria de compartilhar um hack rápido para esse problema. (Isso também resolve o problema da idade 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: ")))
PS Este código é para python 3.x.
Abordagem funcional ou " olha só, sem 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 se você quiser ter uma mensagem de "entrada incorreta" separada de um prompt de entrada como em outras respostas:
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?
-
Essa combinação deprompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
itertools.chain
eitertools.repeat
criará um iterador que produzirá strings"Enter a number: "
uma vez e"Not a number! Try again: "
um número infinito de vezes: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)
- aquimap
aplicará todas asprompts
strings da etapa anterior àinput
função. Por exemplo: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
estr.isdigit
para filtrar essas strings que contêm apenas dígitos:only_digits = filter(str.isdigit, replies) for reply in only_digits: print(reply)
E para obter apenas a string dos primeiros 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
.
Outras regras de validação:
Métodos de string: é claro que você pode usar outros métodos de string, como
str.isalpha
obter apenas strings alfabéticas oustr.isupper
apenas maiúsculas. Veja os documentos para a lista completa.Teste de associação:
Existem várias maneiras diferentes de realizá-lo. Um deles é usando o__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
Comparação de números:
Existem métodos de comparação úteis que podemos usar aqui. Por exemplo, 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
Ou, se você não gosta de usar métodos dunder (dunder = double-underscore), você sempre pode definir sua própria função, ou usar as do
operator
módulo.Existência de caminho:
Aqui pode-se usar apathlib
biblioteca e seuPath.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
Limitando o número de tentativas:
Se você não quiser torturar um usuário perguntando algo infinitas vezes, pode especificar um limite em uma chamada de itertools.repeat
. Isso pode ser combinado com o fornecimento de um valor padrão para a next
função:
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!
Dados de entrada de pré-processamento:
Às vezes, não queremos rejeitar uma entrada se o usuário a forneceu acidentalmente EM MAIÚSCULAS ou com um espaço no início ou no final da string. Para levar em conta esses erros simples, podemos pré-processar os dados de entrada aplicando métodos str.lower
e str.strip
. Por exemplo, para o caso de teste de associação, o código será semelhante a este:
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
No caso de você ter muitas funções para usar no pré-processamento, pode ser mais fácil usar uma função que execute uma composição de função . Por exemplo, usando o daqui :
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 regras de validação:
Para um caso simples, por exemplo, quando o programa pede idade entre 1 e 120 anos, basta adicionar outro 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)
Mas, no caso de haver muitas regras, é melhor implementar uma função que execute uma conjunção lógica . No exemplo a seguir, usarei um pronto a partir daqui :
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
Infelizmente, se alguém precisa de uma mensagem personalizada para cada caso de falha, então, infelizmente, não há uma maneira muito funcional. Ou, pelo menos, não consegui encontrar um.
Então, eu estava mexendo em algo semelhante a isso recentemente e descobri a seguinte solução, que usa uma forma de obter entrada que rejeita lixo, antes mesmo de ser verificado de qualquer maneira lógica.
read_single_keypress()
cortesia 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()
Você pode encontrar o módulo completo aqui .
Exemplo:
$ ./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!
$ _
Observe que a natureza dessa implementação é que ela fecha o stdin assim que algo que não é um dígito é lido. Não apertei enter depois a
, mas precisava depois dos números.
Você poderia mesclar isso com a thismany()
função no mesmo módulo para permitir apenas, digamos, três dígitos.
Usando clique :
Click é uma biblioteca para interfaces de linha de comando e fornece funcionalidade para solicitar uma resposta válida de um usuário.
Exemplo simples:
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 como ele converteu o valor da string em um float automaticamente.
Verificar se um valor está dentro de um intervalo:
Existem diferentes tipos personalizados fornecidos. Para obter um número em um intervalo 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
Também podemos especificar apenas um dos 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
Teste de associação:
Usando click.Choice
tipo. Por padrão, essa verificação diferencia maiúsculas de 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
Trabalhando com caminhos e arquivos:
Usando um click.Path
tipo, podemos verificar os caminhos existentes e também resolvê-los:
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
Ler e gravar arquivos pode ser feito por 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!
Outros exemplos:
ConfirmaÇão Da Senha:
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 padrão:
Nesse caso, basta pressionar Enter(ou qualquer tecla que você usar) sem inserir um valor para obter um valor padrão:
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."
Com base nas excelentes sugestões de Daniel Q e Patrick Artner, aqui está uma solução ainda mais 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)
Optei por instruções explícitas if
e em raise
vez de um assert
, porque a verificação de asserção pode ser desativada, enquanto a validação deve estar sempre ativada para fornecer robustez.
Isso pode ser usado para obter diferentes tipos de entrada, com diferentes condições de validação. Por exemplo:
# 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, para responder à pergunta 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.")
Tente 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')
Sim, estou 6 anos atrasado desde o 🎉, mas essa pergunta merece uma resposta mais atualizada.
Separação de preocupações
Eu sou um grande fã da filosofia Unix "Faça uma coisa e faça-a bem" . Nesse tipo de problema, é melhor dividir o problema em
- Peça entrada com
get_input
até que a entrada esteja ok. - Valide em
validator
função. Você pode escrever diferentes validadores para diferentes consultas de entrada.
Pedindo entrada
Pode ser tão simples quanto (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)
Exemplo
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'
Nota para Python 3.8+
No Python 3.8+ você pode usar o operador walrus
def get_input(prompt, validator, on_validationerror):
while not validator(value := input(prompt)):
print(on_validationerror)
return value
Embora um bloco try
/ except
funcione, uma maneira muito mais rápida e limpa de realizar essa tarefa seria 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.")
Boa pergunta! Você pode tentar o seguinte código para isso. =)
Este código usa ast.literal_eval () para encontrar o tipo de dados de input ( age
). Em seguida, segue o seguinte algoritmo:
Peça ao usuário para inseri-la
age
.1.1. Se
age
éfloat
ouint
tipo de dados:
Verifique se
age>=18
. Seage>=18
, imprima a saída apropriada e saia.Verifique se
0<age<18
. Se0<age<18
, imprima a saída apropriada e saia.Se
age<=0
, peça ao usuário para inserir um número válido para a idade novamente, ( ou seja, volte para a etapa 1.)1.2. Se
age
não forfloat
ouint
tipo de dados, peça ao usuário para inserir sua idade novamente ( ou seja, volte para a etapa 1.)
Aqui está o 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.")
Você sempre pode aplicar a lógica if-else simples e adicionar mais uma if
lógica ao seu código junto com um for
loop.
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á um banheiro infinito e você deverá entrar na era, indefinidamente.
O código abaixo pode ajudar.
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='')
Se você quiser ter o máximo de tentativas, digamos 3, use o código abaixo
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: Isso usa recursão.
Use try-except para lidar com o erro e repita-o novamente:
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")