Re: Overloading function calls

Guido.van.Rossum@cwi.nl
Wed, 01 Jun 1994 14:56:09 +0200

(Only responses to points where we don't already fully agree or don't
all know it yet :-)

> So one vote for leaving len/nonzero exactly as they are!

Yes.

> I.e., if none of __eq__/__lt__/etc are defined, and __cmp__ isn't
> defined, then a relational operator maps to the default general object
> comparison. Do you really want to change that?

Nah, I guess I wasn't awake. If __cmp__ doesn't exist the default
comparison must be used. (We may decide that < > <= >= should fail
for objects where they aren't explicitly defined, but == must
certainly be defined on all type.)

> 1) __ne__ doesn't exist; "!=" maps to "not __eq__", else to __cmp__
> != 0, else ???. [tim, in benign dictator mode]

On second thoughts I agree with this.

> 1) __not_in__ doesn't exist; 'not in' maps to "not __in__", else to ???

Likewise.

> "???" is a bit of a different question, in this case, because given the
> possibility of __eq__ methods, the default "in" logic may want to use the
> __eq__ method if the class defines __eq__. One danger of "magic" is that
> it propagates in not-entirely-obvious ways, eh?

Huh? If there's no __in__, the default implemenation should be used
which takes the second argument as a sequence, extracts the elements
one at a time starting at index 0, and compares them with the left
operand for equality. The latter operation should of course be
implemented as if '==' was used.

> One other: in
>
> if obj1 in obj2:
>
> to which object is __in__ directed <0.9 grin>? obj2.__in__ seems right
> to me, since it's presumably the "structured" object; perhaps unfortunate
> that __in__ then sees its arguments in right-to-left order, but no big
> deal.

Oops, yes. I suggest that the name should be __contains__ rather than
__in__, to make this awfully clear.

The rest of Tim's message is about how to handle things like
"3/complex_number". Currently this is done by calling the RHS'
__coerce__ with reversed arguments. Tim mentions the possibility of
defining separate methods for reversed operators (I imagine with names
like __div_rev__) but doesn't like it. But I don't see any other
solution that would really work. It may be possible to supply
__coerce__ with complete information (e.g. the name of the operator
that is about to be applied as well as a bit indicating reversed
arguments) but then it's almost easier to do the whole operation in
__coerce__ (1/2 :-). Maybe there should also be a __coerce_rev__ (if
it isn't defined, __coerce__ should be called with reversed arguments,
if it exists -- if there's no __coerce__, the __div_rev__ is called
with the unadorned arguments to the original operator).

I would almost concur that __coerce__ is not such a good idea after
all -- each individual __add__, __mul__ etc. could easily call it
explicitly if necessary. However it is essential for *built-in*
numerical types, whose implementations all require two arguments of
the same type. (Even the shift operators, where this is actually
ridiculous.)

On the other hand, if you are implementing a regular numeric type
(e.g. Rational or Complex), then having __coerce__ can save you a line
per function. (Having __coerce__ called automatically may also be a
little faster but I'm less sure there.)

As long as user-defined types are at the top of the numerical type
hierarchy, I'm not sure that having __coerce__ is more than a
convenience. How about junking it?

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