Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

PsySc0rpi0n

Verificação do user input

Recommended Posts

PsySc0rpi0n

Estou a tentar fazer um simples programa mas ainda não consegui!

Estou a pedir ao user um valor. E quero certificar-me que é um número... Numérico... Não alfanumérico!

Já tentei várias abordagens mas ainda não consegui:

from math import frexp
number = float(raw_input("Enter a number:"))
print "Type is: {}".format(type(number))

Até aqui tudo bem.

Mas depois para verificar se é um valor numérico estou a fazer:

while number.isdigit() == False
   print "That is not a number! Try again!"
   number = float(raw_input("Enter a number:"))

Mas isto dá erro:

AttributeError: 'float' object has no attribute 'isdigit'

Como é que faço isto se os floats não têm o método isdigit???

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
djthyrax

Se a memória não me falha (não tenho aqui Python instalado), se tentares fazer float() de algo que não seja válido, é feito raise de uma excepção. É uma questão de apanhares a mesma e fazeres o que precisas :)


Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Ainda não cheguei a esse ponto das exceptions mas vou ver disso.


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Tentei assim mas continua a dar erro...

Eu percebo porquê e para corrigir o erro bastava fazer um cast para float aquando do "raw_input" mas assim a função validate passa a ser redundante e se eu colocar lá "45.a", isto é convertido para float e portanto o retorno da função validate é sempre True, acho eu!

from math import frexp as frexp

def validate(userInput):
   try:
       type(userInput) == float
       valid = True
   except Exception:
       valid = False
   return valid

number = raw_input("Enter a number: ")
print "Type is: {}".format(type(number))#just for debug purposes

print "Validate return value: {}".format(validate(number))

while validate(number) == False:
   print "That is not a number! Try again!"
   number = raw_input("Enter a number: ")

print "{}".format(frexp(number))

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Acabei por fazer assim:

from math import frexp

check = 0
number = raw_input("Enter a number:")

while check != 1:
   try:
       number = float(number)
       print "{}".format(frexp(number))
       check = 1
   except Exception:
       print "That is not a number!"
       number = raw_input("Enter a number:")

Mas não faço ideia se o método é correcto ou se é solução de pedreiro.

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
pwseo

PsySc0rpi0n,

Estás a fazer confusão com várias coisas em simultâneo. Vamos por partes.

Em primeiro lugar, interessa perceber que isdigit() só existe em strings. Por esse motivo, quando defines number = float(...) e depois tentas fazer number.isdigit() é-te devolvido um erro (e muito bem!) que indica que esse atributo não existe para objectos do tipo float, apenas para os do tipo str.

Outra questão importante: ao utilizares isdigit(), estarias a perder todos os casos onde o float tivesse casas decimais, pois esta função só devolve True para números inteiros.

Passemos então ao penúltimo excerto de código que colocaste.

A tua validate() vai ser sempre verdadeira. Isto acontece porque tu tens uma linha onde perguntas se type(userInput) == float, mas como essa condição não está inserida num if, o resultado (seja ele True ou False) nunca será utilizado. Na linha seguinte defines que valid = True (isto acontece sempre) e, uma vez que não há aqui hipótese alguma de haver uma excepção, o valor final será sempre True.

Para que a excepção funcionasse como queres, a conversão para float teria que acontecer dentro de validate().

Por estes motivos, a execução do teu código diria sempre que o tipo é str e que validate() foi True, falhando depois na aplicação de frexp pois não terias um float.

Algumas outras coisas que me incomodam:

  • Escreve apenas from math import frexp (acrescentar as frexp fica mal)
  • Já te expliquei que print "{}".format(...) é o mesmo que escrever print ... (ou seja, se a tua string de formatação é apenas "{}" não uses format!)

E agora o último excerto de código:

O ideal seria abstraires o conceito de «pedir um float ao utilizador» para uma função. Dessa forma, podes depois utilizar a função de forma mais clara:

def ask_for_float():
   try:
       return float(raw_input('Float? '))
   except ValueError:
       # Não era um float válido, devolvemos None
       return None

have_float = False
while not have_float:
   f = ask_for_float()
   have_float = f != None  # Se f não for None, então have_float é True

   # Podemos imprimir uma mensagem de erro aqui 
   if f is None:
       print "That is not a number!"

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Pois, os primeiros pedaços de código já tinham ido à vida. Já iniciei este post há uns dias.

Mas o teu code apenas verifica se o que foi inserido é um float ou não, certo?

Depois ainda tenho que incorporar a função que quero usar.


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
pwseo

Já iniciei este post há uns dias.

Ontem :P

Sim, o meu código faz isso. O teu também, mas mistura mais coisas, nomeadamente o processo de pedir o número, verificar se é válido e emitir avisos.

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Ontem :P

Sim, o meu código faz isso. O teu também, mas mistura mais coisas, nomeadamente o processo de pedir o número, verificar se é válido e emitir avisos.

Pois, parecia ter sido há mais dias!

Deixa cá tentar então usar esse code e alterar o meu!

Outra coisa, o frexp devolve um tuple... É possível separar aqueles dois valores e usá-los para outros fins?


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Ok, já vi como decompôr um tuple... É mais fácil que o que parece!

Fiz assim...

from math import frexp

def ask_for(typ, prompt):
   try:
       return typ(raw_input(prompt))
   except ValueError, TypeError:
       print 'Invalid {!r} value.'.format(typ)

mant = 0.0 
exp  = 0 
isfloat = False
while not isfloat:
   number = ask_for(float, "Enter a number: ")
   isfloat = (number != None)
   if number is not None:
       mant, exp = frexp(number)
       print "The mantissa is {} and the exponent is {}!".format(mant, exp)

Está melhor???


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Sim, bastante melhor :)

Eu já estive a ler sobre aquele

!r

mas não percebi muito bem como e quando aquilo se pode usar e o que aquilo faz...


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
pwseo

PsySc0rpi0n,

Tens que começar por perceber o que faz a função repr() (vê em Built-in functions), mas essencialmente a sua função é devolver uma representação textual de um objecto.

O especificador !r dentro de uma string de formatação é meramente um atalho para essa função repr(), assim:

a = [ 1, 2, 3, 4, 5 ]

# em vez disto:
print "a = {}".format(repr(a))

# podes escrever isto:
print "a = {!r}".format(a)

Tudo isto tem muito mais importância quando crias objectos e classes tuas, e queres definir uma representação textual decente... Para os tipos de dados pré-definidos, o resultado é bastante previsível.

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Ok, assim acho que já percebi! E pode-se fazer isso para outras built-in functions ou é só para essa? Onde posso ver os atalhos que existem???


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites
pwseo

Tens aqui: Format specification mini-language. De qualquer modo, os únicos atalhos suportados são para repr() e str (!r e !s, respectivamente).

Nota: tenho-te dado os links para a documentação do Python 2.7.x, pois sei que estás no Codecademy e é essa versão que utilizam. No entanto, eventualmente deverás pensar em mudar para o Python 3.x, ok? É mais actual e mais saudável para quem está a começar :)

Share this post


Link to post
Share on other sites
PsySc0rpi0n

Pois.. Eu to smartphone ando com uma cena parecida ao CodeAcademy mas com aversão 3.x...


Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.