Emulating Pascal input

Michael Williams michael.williams at st-annes.oxford.ac.uk
Wed May 22 07:03:20 EDT 2002


Hi,

We're currently running a trial implementation of a teaching course in
Python here at the University of Oxford Physics department. The current
course uses Pascal and, although it works well, is obviously sub-optimal
for a modern undergraduate education.

Details of the results of the trial will be posted to EDU-sig when it is
complete, but for now we're trying to address what we see as a
limitation of Python for introductory programming, namely input.

Consider the following Pascal code:

(******** Pascal code **********)
(* Pascal ascii input of numbers: stdin and file *)
readln(x, y);
readln(fin, x, y);

The first line is for stdin, the second for from file. The variables
x and y will then contain the first two white space separated numbers
the program encounters when that function is called.

Here's how we're currently getting students to do the equivalent in
Python:

######### 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)

Having read through the many threads on this topic on comp.lang.python I
realise and understand that modern programs' input generally requires
thought and customization from the program author. However, we strongly
feel there should be an equivalent to Pascal's readln (which is
basically C's scanf but without the formatting strings) for simple,
generally numerical, whitespace-separated input. 

In the two weeks out trial has been running (one to go), students'
attempts to read in simple two column tables from a file has
consistently caused problems due to the (relative!) complexity of string
splitting.

However, There is no need for a scanf (if your input is sufficiently
complex to require formatting strings then either string or regex
splitting is definitely a more elegant solution).

I have been attempting to write such a function in Python but have been 
struggling with (a) the lack of pointers, and (b) my total ignoarnce of
classes, which I suspect would be helpful. Here's what I have so far
(although note there is no error handling--give it a string response and
it falls over and dies, give it the wrong number of responses and it
falls over and dies, etc., etc.):

############ ninput.py ############

import string

def ninput(n, fin = None, prompt = '', sep = None):
    
    # If not file input then get string from stdin, else get from file
    if fin == None: linestring = raw_input(prompt)
    else: linestring = fin.readline()
    
    # Split up into list with optional seperator argument
    responses = string.split(linestring, sep)
    
    for i in range(len(responses)):
        if '.' in responses[i] or 'e' in responses[i] or \ 
        'E' in responses[i]:
            # i.e. if it looks like a float
            responses[i] = float(responses[i])
        else:
            # i.e if it doesn't look like a float    
            responses[i] = int(responses[i])
            
    # If there was only one response then don't return a list.
    if len(responses) == 1: responses = responses[0] 
    
    return responses[:n]

####################################

And here is a usage example:
>>> x, y  = ninput(2)
5 6.0
>>> print x, type(x)
5 <type 'int'>
>>> print y, type(y)
6.0 <type 'float'>

This has the limitation that the user must pass the number of results
they expect back. This is done implicitly in the Pascal version too (the
number of variables passed to the function). However, error checking is 
difficult as this version stands.

If the student using the ninput function does, e.g.

>>> x = ninput(2)
5 6.0
[5, 6.0] <type 'list'>

This is possibly what should be expected. However, passing the numerical
argument representing the number of results expected does not strike me
as a particularly graceful solution. We would prefer something like the
Pascal way, where the global variables in which the results are to be
stored are passed as parameters. Can anyone suggest a way of doing this?

And if such an equivalent to the Pascal construct was implemented, what
would be the chances of getting it included in, say, the string module
of core Python. We would like such a function but would be reluctant to
use it as we would then be teaching our students a ``dialect'' of
Python.

-- 
Michael Williams





More information about the Python-list mailing list