[Python-Dev] .len() instead of __len__() (was: iterator API inPy3.0)

Michael Chermside mcherm at mcherm.com
Mon Mar 6 14:33:23 CET 2006


Oleg Broytmann writes that he thinks methods are inherently "better" than
methods. He asks for advantages of a function over a method, after first
presenting his arguments for methods over functions:

> -- a method is a more natural way to query or manipulate objects;
> -- a direct method call is faster than two-level call (len() => .__len__());
> -- unnecessary cluttering of builtin namespace; the namespace should(1)
>    contains only really global functions (__import__(), eval(), etc.)

Responding to your first point, "a more natural way" is not an argument...
it's an expression of your personal preference.

Your second point (performance) has some merit -- although one would hope
the difference is small in a good implementation. And your third point
(cluttering the builtin namespace) is a valid and real reason to prefer
methods.

In defense of functions, my first exhibit is the following snippet of Java
code:

  /** Returns b^2 - 4ac */
  public BigDecimal determinant(BigDecimal a, BigDecimal b, BigDecimal c) {
    return b.multiply(b).subtract(new BigDecimal(4).multiply(a).multiply(c));
  }

In other words, some things are less clear when written using the notation
used for method invocation. That is particularly true when there are
multiple objects involved and no clear reason to prefer one over another
as the "object performing the action". In languages with multiple dispatch,
like CLOS, everything looks like a function for exactly this reason.

My second exhibit is also some Java code:

  public int numItems(Object o) {
    if (o instanceof Collection) { // includes List, Set
      return ((Collection) o).size();
    } else if (o instanceof Dictionary) {
      return ((Dictionary) o).size();
    } else if (o instanceof CharSequence) { // includes String, StringBuffer
      return ((CharSequence) o).length();
    } else if (o instanceof Object[]) {
      return ((Object[]) o).length;
    } else {
      throw new IllegalArgumentException();
    }
  }

The inconsistancy here is amazing... length, length(), size(). You could
put it down to poor interface design by the Java team, but you must
admit, individual objects are designed in isolation, but when there
exists a common lanugage protocol like Python's builtin len() and __len__,
that developers of individual objects go out of their way to make them
conform with the common protocol... and in the end that makes them more
usable.

I'm sure there are additional arguments, but these are the first few I
came up with. Of course, in nearly all cases, I prefer using methods...
but len() is such a powerful concept applicable across MANY diverse
kinds of objects, that I have no objection to granting it space in the
builtin namespace.

By the way... you write:

> (1) I am a perfectionist and I partially disagree with "practicality beats
> purity"; I would really love a small uncluttered builtin namespace in
> Python.

I just wanted to point out that one of the things I *LOVE* about Python
is that the design of name resolution in Python ensures that no
programmer need suffer from the size of the builtin namespace. If you
never use certain builtins, perhaps "hex" or "super", then go ahead
and use those as identifiers in your code. Avoid only that portion of
the builtin namespace that you feel is worth keeping.

-- Michael Chermside


More information about the Python-Dev mailing list