[Edu-sig] Emulating Pascal input

Kirby Urner urnerk@qwest.net
Wed, 22 May 2002 12:42:10 -0700


>
>######### Python code ###########
># Either: stdin
>linestring = raw_input()
>
># Or: file
>linestring = f.readline()
>
>linelist = string.split(linestring)
>x = int(linelist[0])
>y = int(linelist[1])
>
># Or perhaps
>linestring = raw_input()
>x,y = string.split(linestring)  # x and y are now strings eg. '1'
>                                 # and '2'
>x = int(x)
>y = int(y)

I know people generally say eval() is "bad" but if you're
a student writing your own programs to read your own data
(not writing some generic thing for over-the-web use) it's
unreasonable to expect iron-clad protection against "abuse"
at every turn.

Just do what works.  It's your sandbox, after all.  If
you're intent upon writing malicious stuff, there's no
protecting you from yourself no matter how good a coder
you are.

If it *is* your sandbox, then splitting space-separated
string elements that you know represent numeric data, and
evaluating them to lists containing actual integers or
floats, is pretty straightforward:

def getdata(strdata):
    return [eval(i) for i in strdata.split()]

  >>> getdata('1.2  7e6 -1  10.39')
  [1.2, 7000000.0, -1, 10.390000000000001]

Given x,y = [1,2] is legal syntax, you can write
stuff like:

x,y,z = getdata(f.readline())

where readline() gets you the next 3 numbers in character
form.  x,y and z end up with integer or float values.

This problem comes up a lot on the tutor list.  To quote
Alan, author of a bestselling Python book:

   > I'd like to convert a string to either a float or an integer
   > ``intelligently", i.e.:

   The easy way would be to use eval()
   All the usual caveats around using eval()
   (and exec()) apply of course....

That's from earlier today.

Another option, if you know the data is either ints or
floats, is to apply int() to the string without pre-checking.
int('2.0') is an error, as is int('2e3').  So if int can't
deal with it, pass it on to float:

def getdata2(strdata):
    rtnval = []
    for i in strdata.split():
      try:
         rtnval.append(int(i))
      except:
         rtnval.append(float(i))
    return rtnval

  >>> getdata2('1.2  7e6 -1  10.39')
  [1.2, 7000000.0, -1, 10.390000000000001]

If you don't trust the data to be all ints or floats,
another level could be added, and/or allow it to
crash gracefully (cuz the data must be corrupt).

Kirby