My Python annoyances

Alex Martelli aleax at mac.com
Fri May 4 10:43:52 EDT 2007


Chris Mellon <arkanes at gmail.com> wrote:

> > > I am unqualified to comment on the Python philosophy, but I would like
> > > for my function to do some basic error checking on its arguments.
> >
> > By "basic error checking" I mean "verify that the file argument actually
> > is a file-like object".  By same interface, do you mean that I should
> > check for the methods that I depend on?  That sounds easy enough.
> 
> You should "check" for the methods by calling them. If the object
> doesn't support the method in question, you will get a runtime
> exception. Premature inspection of an object is rarely useful and
> often outright harmful.

However, hoisting method extraction out of the loop is often useful,
because it may speed up operations, and when you do that you might as
well use a try/except AttributeError to provide better diagnostics if
something is missing.  E.g., suppose you have a need to slurp away one
char at a time from a file until you get a 'Z':

def readToZ(f):
    while True:
        c = f.read(1)
        if c == 'Z': return
        elif not c: raise ValueError, "No Z in file f"

this may also raise IOError if the read fails, AttributeError if f does
not have a read method, TypeError (or who knows what) if f.read is not
callable, or does not let you call it with one int argument, etc, etc.

A slightly faster approach:

def readToZ(f):
    read = f.read
    while True:
        c = read(1)
        if c == 'Z': return
        elif not c: raise ValueError, "No Z in file f"

this has exactly the same exception-behavior as the previous version.
It's hardly an error to tweak that behavior slightly:

def readToZ(f):
    try: read = f.read
    except AttributeError: raise TypeError, "%s has no read" % type(f)
    while True:
        c = read(1)
        if c == 'Z': return
        elif not c: raise ValueError, "No Z in file f"

going to horrid amounts of trouble to check that the call to read(1)
won't produce weird failures would be unwarranted, but making one case
of AttributeError into a TypeError in this way is quite OK, for example.


Alex



More information about the Python-list mailing list