[Python-Dev] defaultdict and on_missing()

Guido van Rossum guido at python.org
Thu Mar 2 04:44:46 CET 2006

On 3/1/06, Brett Cannon <brett at python.org> wrote:
> But moving over to more attributes for how we access basic interfaces
> seems great to me.

We shouldn't approach this as "methods good, functions bad" -- nor the
opposite, for that matter.

When all things are equal, I'd much rather do usability studies to
find out what newbies (who haven't been given the OO kool-aid yet)
find easier. For example, math functions are typically written as
sin(x) -- I wouldn't want to switch that to x.sin() and I think most
people would agree.

But often, all things aren't equal. Sometimes, a single algorithm can
be applied to a large set of different types, and then making it a
method is a waste (forcing each type to reimplement the same
algorithm). sin() is actually an example of this (since it applies to
int, long and float). Other times, the same conceptual operation must
be implemented differently for each type, and then a method makes more
sense. I like to think of list.sort() as an example of this -- sorting
algorithms are tightly coupled to internal data representation, and a
generic sort function for mutable sequences would likely be of
theoretical interest only -- in practice it would be much slower than
an implementation that can make use of the internal representation

Operations with two or more arguments are often better expressed as
function calls -- for example, map() and filter() don't make much
sense as methods on callables or sequences.

str.join() is an interesting case, where usability studies may be
necessary. I've often been asked why this isn't a list method -- but
of course that would be less general, since joining strings applies
equally well to other types of sequeces (and iterables). Making it a
string method is arguably the right thing to do, since this operation
only makes sense for strings. But many people (not me!) find the ",
".join(seq) notation hard to read; some other languages use a built-in
function join(seq, str) instead, which is arguably more readable. The
type of such a polymorphic function is easily specified:
join(sequence[T], T) -> T, where T is a string-ish type. (It should
make sense for T==bytes as well; I'm not so sure about T==list though.

One problem with the methods approach is that there's less pressure to
use the same API for all object types (especially with duck typing).
For an example of methods gone horribly wrong, look at Java, where you
have <bultin-array>.length, String.length(), and Collection.size().
Give me len() any day. I believe Ruby has similar confusing diversity
for looping (each/forEach).

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

More information about the Python-Dev mailing list