> So one vote for leaving len/nonzero exactly as they are!
> 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 ???
> "???" 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
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
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>