A maneira mais simples de fazer isso é colocar o input
método em um loop while. Use continue
quando receber uma entrada ruim e break
sair do circuito quando estiver satisfeito.
Quando sua entrada pode gerar uma exceção
Use try
eexcept
para detectar quando o usuário digita 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 o 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 solicitar muitos valores diferentes ao usuário, pode ser útil colocar esse código em uma função, para que você não precise digitá-lo novamente 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 criar 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
Esse método funciona, mas geralmente é considerado de 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 que o while True
método, mas viola o princípio de não se repetir de desenvolvimento de software. Isso aumenta a probabilidade de erros no seu sistema. E se você quiser voltar para o 2.7 alterando input
para raw_input
, mas alterar acidentalmente apenas o primeiro input
acima? Está SyntaxError
apenas esperando para acontecer.
A recursão explodirá sua pilha
Se você acabou de aprender sobre recursão, pode ser tentado a usá-lo get_non_negative_int
para poder 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 digitar dados inválidos várias vezes, o script será encerrado com a RuntimeError: maximum recursion depth exceeded
. Você pode pensar que "nenhum tolo cometeria 1000 erros seguidos", mas está subestimando a ingenuidade dos tolos!
input
por loop e o loop ficará muito curto, mas a condição pode se tornar bastante longa ...Por que você faria um
while True
e, em seguida, interromperá esse ciclo enquanto também pode colocar seus requisitos na instrução while, pois tudo o que você deseja é parar quando tiver a idade?Isso resultaria no seguinte:
isso funcionará, pois a idade nunca terá um valor que não fará sentido e o código seguirá a lógica do seu "processo de negócios"
fonte
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.)
PS Este código é para python 3.x.
fonte
def
.def f(age):
é muito mais claro do quef = lambda age:
Então, eu estava mexendo com algo parecido com isso recentemente, e vim com a seguinte solução, que usa uma maneira de obter entradas que rejeitam lixo, antes mesmo de serem verificadas de maneira lógica.
read_single_keypress()
cortesia de https://stackoverflow.com/a/6599441/4532996Você pode encontrar o módulo completo aqui .
Exemplo:
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ê pode mesclar isso com a
thismany()
função no mesmo módulo para permitir apenas, digamos, três dígitos.fonte
Abordagem funcional ou " olhe mum no loops! ":
ou se você deseja que uma mensagem de "entrada incorreta" seja separada de um prompt de entrada, como em outras respostas:
Como funciona?
itertools.chain
eitertools.repeat
criará um iterador que produzirá seqüências de caracteres"Enter a number: "
uma vez e"Not a number! Try again: "
um número infinito de vezes:replies = map(input, prompts)
- aquimap
aplicará todas asprompts
strings da etapa anterior àinput
função. Por exemplo:filter
estr.isdigit
para filtrar as strings que contêm apenas dígitos: E para obter apenas a primeira string que usamos apenas dígitosnext
.Outras regras de validação:
Métodos de seqüência de caracteres: é claro que você pode usar outros métodos de seqüência de caracteres, como
str.isalpha
obter apenas seqüências alfabéticas oustr.isupper
obter 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:Comparação de números:
Existem métodos úteis de comparação que podemos usar aqui. Por exemplo, para
__lt__
(<
):Ou, se você não gosta de usar métodos dunder (dunder = sublinhado duplo), sempre pode definir sua própria função ou usar as do
operator
módulo.Existência de caminho:
Aqui é possível usar a
pathlib
biblioteca e seuPath.exists
método:Limitar o número de tentativas:
Se você não quiser torturar um usuário, perguntando-lhe algo inúmeras vezes, poderá especificar um limite em uma chamada de
itertools.repeat
. Isso pode ser combinado com o fornecimento de um valor padrão para anext
função:Pré-processamento de dados de entrada:
Às vezes, não queremos rejeitar uma entrada se o usuário a fornecer acidentalmente no CA CAPS ou com um espaço no início ou no final da string. Para tirar esses erros simples em conta que pode pré-processar os dados de entrada através da aplicação
str.lower
estr.strip
métodos. Por exemplo, para o caso de teste de associação, o código terá a seguinte aparência:No caso em que você possui muitas funções para pré-processamento, pode ser mais fácil usar uma função executando uma composição de função . Por exemplo, usando o daqui :
Combinando regras de validação:
Para um caso simples, por exemplo, quando o programa solicita idade entre 1 e 120, é possível adicionar outro
filter
:Porém, no caso de existirem muitas regras, é melhor implementar uma função executando uma conjunção lógica . No exemplo a seguir, usarei um pronto aqui :
Infelizmente, se alguém precisar de uma mensagem personalizada para cada caso com falha, receio que não exista uma maneira funcional. Ou, pelo menos, não consegui encontrar um.
fonte
Usando o Click :
Click é uma biblioteca para interfaces de linha de comando e fornece funcionalidade para solicitar uma resposta válida de um usuário.
Exemplo simples:
Observe como ele converteu o valor da string em um flutuador automaticamente.
Verificando 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
:Também podemos especificar apenas um dos limites,
min
oumax
:Teste de associação:
Usando o
click.Choice
tipo Por padrão, essa verificação diferencia maiúsculas de minúsculas.Trabalhando com caminhos e arquivos:
Usando um
click.Path
tipo, podemos verificar os caminhos existentes e também resolvê-los:A leitura e gravação de arquivos podem ser feitas por
click.File
:Outros exemplos:
ConfirmaÇão Da Senha:
Valores padrão:
Nesse caso, simplesmente pressionar Enter(ou qualquer tecla que você usar) sem inserir um valor, fornecerá um valor padrão:
fonte
fonte
Com base nas excelentes sugestões de Daniel Q e Patrick Artner, aqui está uma solução ainda mais generalizada.
Optei por instruções explícitas
if
eraise
não por umaassert
, porque a verificação de asserções pode estar 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:
Ou, para responder à pergunta original:
fonte
Tente este:-
fonte
Enquanto um bloco
try
/except
funcionará, uma maneira muito mais rápida e limpa de realizar essa tarefa seria usarstr.isdigit()
.fonte
Boa pergunta! Você pode tentar o seguinte código para isso. =)
Este código usa ast.literal_eval () para encontrar o tipo de dados da entrada (
age
). Em seguida, segue o seguinte algoritmo:Aqui está o código.
fonte
Você sempre pode aplicar uma lógica if-else simples e adicionar mais uma
if
lógica ao seu código, juntamente com umfor
loop.Este será um banheiro infinito e você será solicitado a inserir a idade indefinidamente.
fonte
Você pode escrever uma lógica mais geral para permitir que o usuário insira apenas um número específico de vezes, pois o mesmo caso de uso surge em muitos aplicativos do mundo real.
fonte
Você pode fazer a declaração de entrada um loop True while, para que ele solicite repetidamente a entrada do usuário e, em seguida, interrompa o loop se o usuário digitar a resposta que você deseja. E você pode usar try e except blocos para lidar com respostas inválidas.
A variável var é apenas para que, se o usuário digitar uma string em vez de um número inteiro, o programa não retorne "Você não pode votar nos Estados Unidos".
fonte
Use a instrução "while" até que o usuário insira um valor verdadeiro e, se o valor de entrada não for um número ou for um valor nulo, pule-o e tente perguntar novamente e assim por diante. No exemplo, tentei responder verdadeiramente à sua pergunta. Se supusermos que nossa idade está entre 1 e 150, então o valor de entrada é aceito, caso contrário, é um valor errado. Para encerrar o programa, o usuário pode usar a tecla 0 e inseri-la como um valor.
fonte
Mais uma solução para usar a validação de entrada usando uma validação personalizada
ValidationError
e uma faixa (opcional) para entradas inteiras:Uso:
Resultado:
fonte
Aqui está uma solução mais limpa e generalizada que evita blocos repetitivos if / else: escreva uma função que aceita pares (Erro, prompt de erro) em um dicionário e faça toda a sua verificação de valor com asserções.
Uso:
fonte
Entrada persistente do usuário usando a função recursiva :
Corda
Inteiro
e, finalmente, o requisito de pergunta:
fonte
A solução simples seria:
Explicação do código acima: Para uma idade válida, ela deve ser positiva e não deve ser maior que a idade física normal, por exemplo, a idade máxima é 120.
Em seguida, podemos solicitar a idade do usuário e, se a entrada por idade for negativa ou superior a 120, consideraremos a entrada inválida e solicitaremos que o usuário tente novamente.
Depois que a entrada válida é inserida, realizamos uma verificação (usando a instrução if-else aninhada) se a idade é> = 18 ou vice-versa e imprimimos uma mensagem se o usuário está qualificado para votar
fonte
pegue a entrada como string e use isdigit () para verificar se a entrada possui apenas dígitos, não está vazia, não pode ser -ve
fonte