Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

Publicaciones sobre programming (publicaciones antiguas, página 52)

Una pregunta inocente...

To­do em­pe­zó cuan­do "Ga­li­leo Ga­li­lei" pre­gun­tó co­mo ha­cer una co­sa muy sim­ple. Él mos­tró es­te có­di­go:

age = int(raw_input('Cual es tu edad?'))
if age<18:
    print 'Sos menor'
else:
    print 'Sos mayor'

En rea­li­dad el ori­gi­na­l... era un po­co más gua­ran­go, pe­ro el có­di­go es bá­si­ca­men­te el mis­mo. has­ta ahí na­da ra­ro. Pe­ro en­ton­ces pre­gun­tó es­to:

Có­mo pue­do ha­cer que si el usua­rio en­tra al­go que no es un nú­me­ro, ha­ga al­go ti­po:

print 'No tengo poderes de supervaca'

o

print 'Error de tipeo'

Uno se ima­gi­na­ría que esa cla­se de pre­gun­ta pue­de pro­du­cir una o dos res­pues­ta­s. ¿No?

Efec­ti­va­men­te así es, y se ven las res­pues­tas de Fa­cun­do Ba­tis­ta o Eze­quiel.

Pe­ro­... que pa­sa­ría si que­re­mos se­guir pre­gun­tan­do cuan­do el usua­rio en­tra un no­-­nú­me­ro?

En­ton­ces ami­go­s... es una cues­tión de gus­to, y es to­do cul­pa de Juan Pe­dro Fi­sano­tti.

Acá es­tá mi idea:

while True:
    edad=raw_input('¿Cuantos años tenes?')
    if edad.isdigit():
        break
    print 'No ingresaste un numero!'

Sí, lo ad­mi­to, un po­co a la an­ti­gua. Y hu­bu gri­tos de "no, break es una por­que­ría, no es­tá bien", lo que lle­va a és­to, de Ma­nuel Aráoz

age = raw_input('Tu edad?')
while not age.isdigit():
    print "No es un número!"
    age = raw_input('Tu edad?')

Lo que lle­va a llan­tos de "Te­ner dos raw_i­n­put es feo­!", lo que a su vez pro­vo­ca es­to (nue­va­men­te, Ma­nuel 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á Pa­tri­cio Mo­li­na pe­la la PEP 315.

Y en­ton­ces Ale­jan­dro San­tos di­ce al­go co­mo "Es­to es más fa­cil en C por­que po­de­mos asig­nar va­lo­res a edad en la con­di­ción del whi­le". Acuér­den­se de es­to.

Aho­ra Pa­blo Zi­llia­ni da su ver­sió­n, que, de­bo de­ci­r, es per­fec­ta en cier­ta for­ma:

age = reset = msg = 'Edad?: '
while not age.isdigit():
    age = raw_input(msg)
    msg = "%r no es un numero!, %s" % (age, reset)

print age

En­ton­ces Ga­briel Ge­ne­lli­na de­ci­de de­fen­der el uso de break pe­gán­do­nos a to­dos en la ca­be­za con Knu­th lo que de­be­ría te­ner un efec­to mu­cho más po­ten­te que men­cio­nar a Hi­tle­r.

Y va­mos lle­gan­do a aguas po­co na­ve­ga­ble­s. Acá es­tá la pro­pues­ta de news , que ad­mi­ro. A una res­pe­tuo­sa dis­tan­cia.

Pri­me­ro el có­di­go re­le­van­te:

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!"

¿Pe­ro qué, exac­ta­men­te, es firs­tTrue?

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

En­ton­ces yo men­ciono ge­ne­ra­do­res, lo que lle­va a es­to, por Clau­dio Frei­re, que ca­si fun­cio­na:

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 en­ton­ces Fa­bian Ga­lli­na es el se­gun­do en men­cio­nar que en C po­dés asig­nar en con­di­cio­nes.

No pien­so acep­tar­lo. C no pue­de ser más fá­cil pa­ra es­to!

Así que con una ayu­di­ta del cook­book...

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 en­ton­ce­s, Pa­blo pos­tea es­ta jo­yi­ta:

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 pa­re­ce a mí, lo me­nos tri­vial que se pue­de lle­gar con es­te pro­ble­ma. Cla­ro que el hi­lo no se mu­rió to­da­vía ;-)

Preparando un release de rst2pdf para la semana que viene

Ho­la, me lla­mo Ro­ber­to Al­si­na, soy un ex de­sa­rro­lla­dor de KDE, pro­gra­ma­dor ama­teu­r[1]_, fan de py­tho­n, mu­cho gus­to.

Es­te post (y mu­chos otros ;-) es so­bre rs­t2­pdf, una he­rra­mien­ta pa­ra con­ver­tir tex­to res­truc­tu­ra­do en PDF. Por ejem­plo, con­vier­te la re­fe­ren­cia de la bi­blio­te­ca stan­dard de py­thon en es­te PDF (no, no es "ca­li­dad de pro­duc­ció­n" to­da­vía)

Si sos usua­rio de rs­t2­pdf 0.11, o de sphi­nx o de do­cu­tils y que­rés pro­bar una ma­ne­ra al­ter­na­ti­va de crear PDFs, te re­co­mien­do que prue­bes el có­di­go de trunk de SVN.

Es­tas son al­gu­nas de las no­ve­da­des des­de la ver­sión 0.11:

  • PDFBui­l­­de­­r, una ex­­ten­­sión Sphi­nx ex­­ten­­sion pa­­ra ge­­ne­­rar PDFs.

  • Ke­r­­ning (re­­quie­­re wo­r­­da­­xe de SVN)

  • So­­­po­r­­te de AAFi­­gu­­re (dia­­gra­­mas usan­­do AS­­CII Ar­­t)

  • Sal­­tos de pá­­gi­­na pue­­den ser pa­­res/i­m­­pa­­res/­­cua­l­­quie­­ra

  • So­­­po­r­­te de co­n­­ta­­do­­­res de pá­­gi­­na avan­­za­­dos (ma­­nua­­le­s, ro­­­ma­­no­­/a­­rá­­bi­­co­­/­­le­­tra­s)

  • Es­­ti­­los mu­­cho más po­­­de­­ro­­­so­­s, so­­­bre to­­­do pa­­ra ta­­bla­s.

  • Unas dos do­­­ce­­nas de bugs arre­­gla­­do­­s.

Así que por fa­vor pro­bá­lo, ca­paz que te gus­ta!

1

Eso só­lo sig­ni­fi­ca que me gus­ta pro­gra­ma­r.

¡Hey! ¡sphinx-rst2pdf-builder funciona!

Me die­ron de­re­cho de es­cri­tu­ra en el re­po de mer­cu­ria­l, así que aho­ra se pue­de ob­te­ner la ver­sión muy muy al­fa acá

Es­to hi­zo sal­tar va­rios bugs en rs­t2­pdf, así que se ne­ce­si­ta rs­t2­pdf de svn pa­ra que te sir­va de al­go.

Qué fun­cio­na:

  • El glo­­s­a­­rio

  • Res­­tru­c­­tu­­red text co­­­mú­n... con al­­gu­­nas ex­­ce­p­­cio­­­nes (e­­je­m­­plo: las no­­­tas al pié no es­­tán bien)

  • Ge­­ne­­ra­­ción de Ín­­di­­ce (no 100%, pe­­ro ti­­po un 75%)

No ten­go ida de qué otras par­tes de sphi­nx re­quie­ren so­por­te es­pe­cí­fi­co en rs­t2­pdf, pe­ro las voy ata­can­do a me­di­da que me en­te­ro.

rst2pdf: casi listo para sphinx

Ese tu­to­ria­l, co­mo to­da la do­cu­men­ta­ción nue­va de py­tho­n, usa sphi­nx.

Ya que sphi­nx es muy po­pu­lar, quie­ro que rs­t2­pdf fun­cio­ne lo me­jor po­si­ble pa­ra pro­du­cir sus PDFs. En­ton­ce­s, con dos co­sas pi­can­do, me em­pe­cé a ras­ca­r.

Ha ha­bi­do al­gún pro­gre­so. Si bien los cam­bios en sphi­nx es­tán só­lo en mi com­pu­ta­do­ra, los voy a pu­bli­car pron­to, y los cam­bios en rs­t2­pdf ya es­tán en SVN.

Acá hay una mues­tra pa­ra abrir el ape­ti­to.


Contents © 2000-2020 Roberto Alsina