Typing arguments in python

Alex Martelli aleax at aleax.it
Wed Apr 16 11:08:31 EDT 2003


Dale Strickland-Clark wrote:

> Dale Strickland-Clark <dale at riverhall.NOTHANKS.co.uk> wrote:
> 
>>danra at walla.co.il (Danra) wrote:
>>
>>>def f(fileobj):
>>>    if not hasattr(fileobj,'write'):
>>>        raise TypeError, "Given arg must have the 'write' attribute."
>>>    .
>>>    .
>>>    fileobj.write('...')
>>
>>You want assert, you do:
>>
>>def f(fileobj):
>>    assert hasattr(fileobj, 'write'), 'Bang! Sort your code out.'
> 
> Obviously, there's a 'not' missing from the above :-(.

Hmmmm, are you sure...?  This raises when the attribute is
missing, which seems likely to be what one desires.

But I prefer a slightly different approach, exemplified at
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52291 --
``Accurate "look before you leap"''.  It mostly comes in handy
when you want to reduce the risk of having done some hard to
reverse "partial state change" by the time you get the exception.

In a case such as this, the idiom would reduce, at a minimum, to:

def f(fileobj):
    write = fileobj.write
    # rest of function follows -- just call write('...') when needed

by extracting the bound-method as the first action of the function,
you ensure the exception happens ASAP -- *AND* you get a nice little
performance boost in many cases too.  You can spend some of that
boost to do a little bit more checking than the above snippets show,
for example:

def f(fileobj):
    write = fileobj.write
    write('')
    # rest of function follows -- just call write('...') when needed

NOW, this ensures you, if you get to the "rest of function" part:
   1. fileobj has a write attribute, AND
   2. that attribute is callable, AND
   3. it is, in particular, callable with a single argument
      that is a plain string

Of course, you need to identify meaningful "no-operation" ways to
call the relevant callables in order to LBYL _very_ accurately.  But
it's often possible and sometimes fruitful to do so.  Of course,
you'll probably want to document this usage accurately.  Incidentally,
the inspiration for "accurate LBYL" came to me from the "Template
Constraints" idiom of C++ (of course, in C++ templates &c are entirely
resolved at compile-time, and so are the "constraints" in the idiom,
but the similarities, in terms of signature-based polymorphism, between
C++ templates and Python functions are still strong).


Alex





More information about the Python-list mailing list