[Python-3000] Abilities / Interfaces

Guido van Rossum guido at python.org
Wed Nov 22 16:53:08 CET 2006


On 11/21/06, Phillip J. Eby <pje at telecommunity.com> wrote:
> At 08:57 PM 11/21/2006 -0800, Guido van Rossum wrote:
> >Phillip, please shorten your posts. You're hogging all the bandwidth I
> >have for thinking about this. Please!
>
> Er, that *was* the shortened version; I actually spent about an hour *just*
> on shortening it.

Ouch.

> I tried to write a short reply to your message, but with little
> success.  So, I'll just rate limit myself by refraining from posting for a
> couple of days.  Will that work?

Sure. Or you could take up my suggestion and spec out addmethod etc.,
trying to do without defop for now. Or answer the email below in less
space than the original.

Here are a few more things to ponder.

1. While I write a lot of code, I don't write much code that could
benefit from interfaces or generic functions much. What I write is
typically a very specific application or a library that speaks a very
specific protocol, not a framework. There's one kind of interface that
could benefit me, and that's a quick way to distinguish between
certain standard types. Examples that keep recurring are things like
the smtplib.SMTP.sendmail() method, whose second argument is either a
string or a list of strings. The optimal way of writing this, IMO, is
a single method that typechecks its 2nd argument. It currently uses
"if isinstance(x, basestring)" but I'd be happier if this could be
written as some kind of check for implementing the String interface.
(If it's neither a string nor a list, I don't really care what
happens, it will just raise an exception a few lines later and that's
perfectly fine for diagnosing the problem). Rewriting this as a
generic method (how do I even create generic methods? I'm sure it's
easy) sounds like a total waste of time and code. Expecting that
authors of alternative String implementations would care enough about
this obscure and super-specialized method to add a binding for their
type (smtplib.SMTP.sendmail[MyStringType] =
smtplib.SMTP.sendmail[str]) would be naive. So every application that
wants to pass a MyStringType to sendmail() needs to do this assignment
itself -- a serious reduction in convenience. If there were an
interface that means "Behaves like a string" then those few brave
souls who write their own string implementation from scratch could
just claim to implement it and their string objects would be welcome
everywhere. (Sure, there might be a few places where they weren't
welcome due to very subtle differences from 'str' -- but I don't
expect those to be simply the lack of a certain method, rather some
invariant involving several objects.) Another example is the many
"open" functions (for opening e.g. tar or zip files, or compressed or
encrypted streams, or parsers) that take either a filename or a file
objects. It is much more convenient to write a single function that
checks if the argument is a string and in that case opens it than to
have to use a generic function. I'm foreseeing that you'll propose
having a standard generic function that takes a string or a stream and
returns a stream -- that is indeed a handy thing to have, except we
still have to know whether the argument was a string or not, because
if we open it, we want to close it, but if we were passed a stream, we
*don't* want to close it.

2. Numbers are another example. They are very common arguments to
functions and methods. Very few people write their own number
implementations, because the built-in ones are so good. But there
*are* people who do, for very specialized reasons (numpy has a whole
slew of new number types). I don't think it makes sense to turn
everything that takes a number as argument into a generic function.
Now, due to duck typing, if you just *use* numbers, and the numpy
folks have done their job, things will just work -- this is your
argument about using generic operations. But as soon as any type
testing happens (e.g. when writing an API that takes either a number
of a string or a list of numbers), I'd much rather have a few "big"
interfaces (Number, RealNumber, Integer) than lots of small ones
Pedroni-style (number-that-support-exponentiation,
number-that-supports-bitwise-and, number-that-supports-left-shift,
...?).

I guess I either don't understand or don't completely buy the
"Pedroni" argument that interfaces should focus on single methods. Or
perhaps numbers and strings (types with rich APIs that are only rarely
re-implemented from scratch) are special cases?

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-3000 mailing list