Typing arguments in python

Danra danra at walla.co.il
Wed Apr 16 15:24:15 CEST 2003


Here's an idea I've been playing with for a syntax for type checking
in python. Instead of trying to explain it, I'll just start off with
an example:

Let's say I want to pass a file object to function f. I could to one
of the following definitions:

def f(fileobj):
    .
    .
    fileobj.write('...')
    .
    .

Or:

def f(fileobj):
    if not hasattr(fileobj,'write'):
        raise TypeError, "Given arg must have the 'write' attribute."
    .
    .
    fileobj.write('...')
    .
    .

The advantages of the second definition are obvious - The fact that
the argument passed doesn't have the write method would be detected
immediately, rather than when trying to call the it.

Why is that so important? Well, for starters in many cases it isn't.
In a simple script or application it really is sufficient to get the
exception only when calling write.

But - what if:

1) The stuff you do before calling write takes a lot of time, which
could be saved if the error is detected when the function is called.
2) The object gets passed around from function to function, and maybe
changes its name on the way. In this case it would be more difficult
to trace the problem from the errorneous call to the original function
call.

Now, once the advantage of the second approach have been verified,
what if in my application, I have a LOT of functions which pass around
file objects? Should I copy the write-attribute checking routine to
all of them? If I have to check a lot of  attributes for a lot of
objects in each function, it becomes a bit of a nuisance, and less
readable.

So the obvious solution is to write a function:

def verify_writable(x):
    if not hasattr(x,'write'):
        raise TypeError,...

and then we could use:

def f(fileobj):
    verify_writable(fileobj)
    .
    .

But it would be more readable if we could use the syntax:

def writable(x):
    if not hasattr(x,'write'):
        raise TypeError,...

def f(writable fileobj):
    .
    .

and also

def f( (readable,writable) fileobj ):
    .
    .

or for value checking:

def f( positive x ):
    .
    .

Of course using such 'typing' for an argument would be permissable,
not mandatory. Basically cause it would mostly be used in big
applications, not just for your everyday script.

To summarize - why do I think such syntax is good?
Because in addition to the advantages of type and value checking
before actually starting to do the work in the function, which could
be done using available syntax - by just calling such checking
functions in the beginning of your function - you get more readable
and obvious code, mostly because such value and type checking *belong*
in the argument list, not inside the function body, IMHO.

P.S. I am not a expert on python or anything of the sort. It could be
that all of the above is just balderdash in your opinions, in which
case feel free to say so :)




More information about the Python-list mailing list