Skip to main content

Ralsina.Me — Roberto Alsina's website

Posts about programming (old posts, page 52)

An innocent question...

There is a very fun­ny thread cur­rent­ly in the PyAr (Python Ar­genti­na) mail­ing list.

It all start­ed when "Galileo Galilei" asked about how to do a very sim­ple thing. He pre­sent­ed this code:

age = int(raw_input('How old are you?'))
if age<18:
    print 'You are underage'
else:
    print 'You are a grownup'

Ok, the orig­i­nal was... not quite as po­lite, but the code is the same. So far, noth­ing strange. But then he asked this:

How can I make it so that if the us­er en­ters some­thing that is not a num­ber, it does some­thing like this:

print 'I have no supercow powers'

or maybe

print 'Typing error'

You can prob­a­bly imag­ine that ask­ing this kind of thing should pro­duce maybe two an­swer­s. Right?

That is in­deed the case, and you can see that in the an­swer by Fa­cun­do Batista or Eze­quiel.

Ex­cep­t... what if we want­ed it to keep ask­ing in case the us­er en­tered not-a-num­ber?

Then, my friend­s... it's about taste, and it's all Juan Pe­dro Fisan­ot­ti's fault.

Here's my take:

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

Yes, I ad­mit, a bit old fash­ioned. And there was a cry of "no, break suck­s, it's not right", which leads to this by Manuel Aráoz

age = raw_input('Your age?')
while not age.isdigit():
    print "That's not a number!"
    age = raw_input('Your age?')

Which caused cries of "Hav­ing raw_in­put twice is ug­ly!", which leads to (a­gain by Manuel Aráoz):

get_age = lambda: raw_input('Your age?')
age = get_age()
while not age.isdigit():
    print 'Not a number!'
    age = get_age()

Here Patri­cio Moli­na digs up PEP 315.

And then Ale­jan­dro San­tos says some­thing like "This is eas­i­er in C, be­cause we can as­sign a val­ue to age in the while's con­di­tion". Please re­mem­ber this.

Now Pablo Zil­liani gives his ver­sion, which is, I must say, per­fect in some ways:

age = reset = msg = 'Age?: '
while not age.isdigit():
    age = raw_input(msg)
    msg = "%r is not a number!, %s" % (age, reset)

print age

Here Gabriel Genel­li­na de­cides to de­fend break by hit­ting ev­ery­one in the head us­ing Knuth which should have a much stronger ef­fect than Hitler.

And now, we start veer­ing in­to weird wa­ter­s. Here is what news pro­pos­es, which I must say, I ad­mire... from a re­spect­ful dis­tance.

First, the rel­e­vant code:

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

But what, ex­act­ly, is first­True?

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

Then, I bring up gen­er­a­tors, which leads to Clau­dio Freire's, which al­most work­s, too:

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

And then Fabi­an Gal­li­na is the sec­ond one to bring up C's as­sign­ments in­side con­di­tion­s.

You know, I can't ac­cept that. I will not ac­cept C be­ing eas­i­er for this.

So, with a lit­tle help from the python cook­book...

age=[1]

while not age |asig| raw_input('Age? '):
    print 'Not a number!'

print u'You are %s years old'%age[0]

You may ask, what's |asig|? Glad you asked!

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)

And then, Pablo posts this gem:

import inspect

def assign(var, value):
    stack = inspect.stack()[1][0]
    stack.f_locals [var] = value
    del stack
    return value

while not assign("age", raw_input('Age? ')).isdigit():
    print u'Not a number!'

print u'You are %s years old' % age

Which is, IMVHO, about as far from triv­ial as you can get here. Of course the thread is not dead yet ;-)

Preparing a rst2pdf release for next week

Since this is the first post that ap­pears in Plan­et Python, a small in­tro is in or­der.

Hi, my name is Rober­to Alsi­na, I am a for­mer KDE de­vel­op­er, am­a­teur pro­gram­mer [1] , python fan.

This post (and many you will see from me) is about rst2pdf, a tool to con­vert re­struc­tured text to PDF. For ex­am­ple, it turns the python li­brary ref­er­ence in­to this PDF (not pro­duc­tion qual­i­ty yet).

If you are a rst2pdf 0.11 user, or a sphinx or do­cu­tils us­er who wants to try an al­ter­na­tive way to cre­ate PDF­s, then I would like your help test­ing the SVN trunk code.

These are some of the new fea­tures since 0.11:

  • PDF­Builder, a Sphinx ex­ten­­sion to gen­er­ate PDF­s.

  • Kern­ing (re­quires wor­­daxe from SVN)

  • AAFig­ure sup­­port (di­a­­grams us­ing ASCII Art)

  • Page­Breaks can be odd­­/even/any

  • Sup­­port for ad­­vanced page coun­ters (man­u­al num­ber­ing, ro­­man/ara­bic/let­ter­s)

  • Much bet­ter styling, spe­­cial­­ly for ta­bles.

  • About two dozen bug­­fix­es.

So, please, take a look, you may like it!

Yay! sphinx-rst2pdf-builder works!

Ok, it kin­da works a lit­tle.

I got com­mit rights in the mer­cu­ri­al re­po, so now you can get the very very al­pha ver­sion here.

This trig­gered sev­er­al bugs in rst2pdf, so you need SVN rst2pdf for it to work.

What work­s:

  • Glos­sary

  • Plain re­struc­­tured text ... with some caveats (ex­am­­ple: foot­notes are semi-bro­ken)

  • In­­dex gen­er­a­­tion (not 100%, but maybe 75%)

I don't know what oth­er pieces of sphinx re­quire spe­cif­ic rst2pdf sup­port, but I will be hit­ting them as they come.

rst2pdf: almost sphinx-ready

Some guys at PyAr are trans­lat­ing the python tu­to­ri­al to span­ish.

That tu­to­ri­al, like all the new python doc­s, us­es sphinx.

Since sphinx is very pop­u­lar, I want rst2pdf to work as well as pos­si­ble as Sphinx's PDF pro­duc­er. So, two dif­fer­ent things itch­ing, I start­ed scratch­ing.

Well, progress has been made. While the sphinx changes cur­rent­ly re­side on­ly on my com­put­er, I will pub­lish them soon, and the rst2pdf changes are al­ready com­mit­ted.

Here's a sam­ple to whet your ap­petite.


Contents © 2000-2024 Roberto Alsina