Re: Overloading function calls

Guido.van.Rossum@cwi.nl
Tue, 31 May 1994 10:57:28 +0200

> Herewith a stab at some overloading principles; bad reactions?

This sounds like a very reasonable proposal. I don't know how much it
would take to imeplement but it doesn't look like it would be
prohibitive. I'll only comment on those points where I don't
agree entirely or have something to add.

> A case could be made that it should apply to __len__/__nonzero__ too,
> the former to overload "len", and the latter to overload Boolean
> contexts; it's not _obviously_ a good idea to say those always mean the
> same thing for user-defined classes. E.g., picture a "logical formula"
> class, where a natural meaning for "len" is the number of atoms in the
> formula, a natural meaning for __getitem__ is to return the i'th left-
> to-right atom, but a natural meaning in a Boolean context is "true iff
> the formula's a tautology". Note too that this kind of class
> combines aspects of both sequence and numeric types (e.g., what could
> be more natural than to define "|" (__or__) to mean the logical
> disjunction of two formulas?).

I would like to stick to the current behavior that if __nonzero__ is
not defined but __len__ is, __len__ is used to determine
truth/falsehood. It is already the case that __nonzero__ overrides
__len__, so if you want them to be different you can do that. The
idiom of testing for falsehood of a sequence instead of testing its
length is so common that it would break too much code if failed for a
user-defined sequence that didn't explicitly define __len__.

> A complication that appears obviously worthwhile here is for a __cmp__
> method to override all methods corresponding to individual relational
> operators.

More precisely: if __eq__ exists, use it, else if __cmp__ exists, use
it, else raise an exception; likewise for the other operators.

There's something to say for not using __ne__ to override !=. I think
this should always be defined as the inverse of __eq__ (or at least
default to that).

I'd also propose having an explicit __in__ method that might define a
quicker implementation of the 'in' operator (e.g. for sorted lists one
could use binary search). __not_in__ is likewise unnecessary since it
can call __in__ and reverse the result.

> + While Python knows what coerce needs to do for built-in types, it can't
> know what's most appropriate for user-defined types. Consequently, if
> __coerce__ exists, Python should be satisified if it returns any 2-tuple
> whatsoever whose 1st component is a class instance.

OK. Then should it still be called if the two instances are already
of the same type and class? (I'd say yes.)

> + One simplifying option I haven't thought enough about: Suppose a
> __coerce__ method only captured explicit instances of the built-in
> "coerce", and implicit instances due to .sort(), "in", and __cmp__ (any
> others?). Then other methods like __div__ etc would be responsible for
> invoking coerce themselves, if they wanted coercion. I suspect that
> would be a signficant step backwards in convenience, though; for many
> "numeric" types, implicit coercion really is a help.

If I understand you correctly this would break things like
3*some_complex_number (where currently the LHS is coerced to complex
before __mul__ is called).

> otoh-too-much-"helpful-magic"-is-what-makes-it-baffling-today!-ly y'rs

What we need is the right amount of magic!

--Guido van Rossum, CWI, Amsterdam <Guido.van.Rossum@cwi.nl>
URL: <http://www.cwi.nl/cwi/people/Guido.van.Rossum.html>