[Python-Dev] type categories

Andrew Koenig ark@research.att.com
Tue, 13 Aug 2002 17:27:19 -0400 (EDT)

Guido> Alex Martelli introduced the "Look Before You Leap" (LBYL) syndrome
Guido> for your uneasiness with (4) (and (5), I might add -- I don't know
Guido> that __iter__ is always safe).  He contrasts it with a different
Guido> attitude, which might be summarized as "It's easier to ask forgiveness
Guido> than permission."  In many cases, there is no reason for LBYL
Guido> syndrome, and it can actually cause subtle bugs.  For example, a LBYL
Guido> programmer could write

Guido>   if not os.path.exists(fn):
Guido>     print "File doesn't exist:", fn
Guido>     return
Guido>   fp = open(fn)
Guido>   ...use fp...

Guido> A "forgiveness" programmer would write this as follows instead:

Guido>   try:
Guido>     fp = open(fn)
Guido>   except IOError, msg:
Guido>     print "Can't open", fn, ":", msg
Guido>     return
Guido>   ...use fp...

Guido> The latter is safer; there are many reasons why the open() call in the
Guido> first version could fail despite the exists() test succeeding,
Guido> including insufficient permissions, lack of operating resources, a
Guido> hard file lock, or another process that removed the file in the mean
Guido> time.

Guido> While it's not an absolute rule, I tend to dislike interface/protocol
Guido> checking as an example of LBYL syndrome.  I prefer to write this:

Guido>   def f(x):
Guido>     print x[0]

Guido> rather than this:

Guido>   def f(x):
Guido>     if not hasattr(x, "__getitem__"):
Guido>       raise TypeError, "%r doesn't support __getitem__" % x
Guido>     print x[0]

I completely agree with you so far.  If you have an object that you
know that you intend to use in only a single way, it is usually right
to just go ahead and use it that way rather than asking first.

Guido> Admittedly this is an extreme example that looks rather silly,
Guido> but similar type checks are common in Python code written by
Guido> people coming from languages with stronger typing (and a bit of
Guido> paranoia).

Guido> The exception is when you need to do something different based
Guido> on the type of an object and you can't add a method for what
Guido> you want to do.  But that is relatively rare.

Perhaps the reason it's rare is that it's difficult to do.

One of the cases I was thinking of was the built-in * operator,
which does something completely diferent if one of its operands
is an integer.  Another one was the buffering iterator we were
discussing earlier, which ideally would omit buffering entirely
if asked to buffer a type that already supports multiple iteration.

>> Some other categories:

>> callable
>> sequence
>> generator
>> class
>> instance
>> type
>> number
>> integer
>> floating-point number
>> complex number
>> mutable
>> tuple
>> mapping
>> method
>> built-in

Guido> You missed the two that are most commonly needed in practice:
Guido> string and file. :-)

Actually, I thought of them but omitted them to avoid confusion between
a type and a category with a single element.

Guido> I believe that the notion of an informal or "lore" (as Jim
Guido> Fulton likes to call it) protocol first became apparent when we
Guido> started to use the idea of a "file-like object" as a valid
Guido> value for sys.stdout.

OK.  So what I'm asking about is a way of making notions such as
"file-like object" more formal and/or automatic.

Of course, one reason for my interest is my experience with a
language that supports compile-time overloading -- what I'm really
seeing on the horizon is some kind of notion of overloading in
Python, perhaps along the lines of ML's clausal function definitions
(which I think are truly elegant).

Guido> Interestingly enough, Jim Fulton asked me to critique the Interface
Guido> package as it exists in Zope 3, from the perspective of adding
Guido> (something like) it to Python 2.3.

Guido> This is a descendant of the "scarecrow" proposal,
Guido> http://www.foretec.com/python/workshops/1998-11/dd-fulton.html (see
Guido> also http://www.zope.org/Members/jim/PythonInterfaces/Summary).

Guido> The Zope3 implementation can be viewed here:
Guido> http://cvs.zope.org/Zope3/lib/python/Interface/

I'll have a look; thanks!