Una pregunta inocente...
Todo empezó cuando "Galileo Galilei" preguntó como hacer una cosa muy simple. Él mostró este código:
En realidad el original... era un poco más guarango, pero el código es básicamente el mismo. hasta ahí nada raro. Pero entonces preguntó esto:
Cómo puedo hacer que si el usuario entra algo que no es un número, haga algo tipo:
o
Uno se imaginaría que esa clase de pregunta puede producir una o dos respuestas. ¿No?
Efectivamente así es, y se ven las respuestas de Facundo Batista o Ezequiel.
Pero... que pasaría si queremos seguir preguntando cuando el usuario entra un no-número?
Entonces amigos... es una cuestión de gusto, y es todo culpa de Juan Pedro Fisanotti.
Acá está mi idea:
while True: edad=raw_input('¿Cuantos años tenes?') if edad.isdigit(): break print 'No ingresaste un numero!'
Sí, lo admito, un poco a la antigua. Y hubu gritos de "no, break es una porquería, no está bien", lo que lleva a ésto, de Manuel Aráoz
age = raw_input('Tu edad?') while not age.isdigit(): print "No es un número!" age = raw_input('Tu edad?')
Lo que lleva a llantos de "Tener dos raw_input es feo!", lo que a su vez provoca esto (nuevamente, Manuel Aráoz:
get_age = lambda: raw_input('Tu edad?') age = get_age() while not age.isdigit(): print 'No es un numero!' age = get_age()
Acá Patricio Molina pela la PEP 315.
Y entonces Alejandro Santos dice algo como "Esto es más facil en C porque podemos asignar valores a edad en la condición del while". Acuérdense de esto.
Ahora Pablo Zilliani da su versión, que, debo decir, es perfecta en cierta forma:
age = reset = msg = 'Edad?: ' while not age.isdigit(): age = raw_input(msg) msg = "%r no es un numero!, %s" % (age, reset) print age
Entonces Gabriel Genellina decide defender el uso de break pegándonos a todos en la cabeza con Knuth lo que debería tener un efecto mucho más potente que mencionar a Hitler.
Y vamos llegando a aguas poco navegables. Acá está la propuesta de news , que admiro. A una respetuosa distancia.
Primero el código relevante:
edad = "0" # Entra igual la primera vez while firstTrue (not edad.isdigit()): edad = raw_input ("¿Cuantos años tenes? ") if not edad.isdigit(): print "No ingresaste un nro!"
¿Pero qué, exactamente, es firstTrue?
import inspect def firstTrue(cond): """ devuelve True siempre la primera vez que se la ejecuta, las veces subsiguientes evalua la condicion """ stack = inspect.stack()[1] # El stack del programa llamador line = stack[2] # Nro de linea desde la que llame a firstTrue del stack if not "line" in firstTrue.__dict__: # Primera vez que llamo a la funcion firstTrue.line = line return True elif firstTrue.line != line: # Llame a la funcion desde otro punto del programa firstTrue.line = line return True return cond
Entonces yo menciono generadores, lo que lleva a esto, por Claudio Freire, que casi funciona:
age = '' def invalidAge(): yield True while not age.isdigit(): print "Not a number" yield True yield False for i in invalidAge(): age = raw_input("Age please: ") print age
Y entonces Fabian Gallina es el segundo en mencionar que en C podés asignar en condiciones.
No pienso aceptarlo. C no puede ser más fácil para esto!
Así que con una ayudita del cookbook...
edad=[1] while not edad |asig| raw_input('Edad? '): print u'Poné un número!' print u'Tenes %s años'%edad[0]
¿Pero qué es |asig|
? ¡Qué buena pregunta!
class Infix: def __init__(self, function): self.function = function def __ror__(self, other): return Infix(lambda x, self=self, other=other: self.function(other, x)) def __or__(self, other): return self.function(other) def __rlshift__(self, other): return Infix(lambda x, self=self, other=other: self.function(other, x)) def __rshift__(self, other): return self.function(other) def __call__(self, value1, value2): return self.function(value1, value2) def opasigna (x,y): x[0]=y return y.isdigit() asig=Infix(opasigna)
Y entonces, Pablo postea esta joyita:
import inspect def assign(var, value): stack = inspect.stack()[1][0] stack.f_locals [var] = value del stack return value while not assign("edad", raw_input('Edad? ')).isdigit(): print u'No es un numero!' print u'Tenes %s años' % edad
Que es, me parece a mí, lo menos trivial que se puede llegar con este problema. Claro que el hilo no se murió todavía ;-)