new-style classes multiplication error message isn't veryinformative

Steven D'Aprano steve at REMOVETHIScyber.com.au
Fri Dec 30 11:26:55 EST 2005


On Fri, 30 Dec 2005 13:23:30 +0000, Jon Guyer wrote:

> Steven D'Aprano <steve <at> REMOVETHIScyber.com.au> writes:
> 
>> 
>> On Fri, 30 Dec 2005 03:47:30 +0000, Jon Guyer wrote:
>> 
>> > We have a rather complicated class that, under certain circumstances, knows
>> > that it cannot perform various arithmetic operations, and so returns
>> > NotImplemented.  As a trivial example:
>> 
>> Why don't you raise the exception yourself?
>> 
>> (Note the difference between NotImplemented and NotImplementedError.)
> 
> Because although A may not know how to multiply B, B might know how to multiply A

Given the way Python is now, that's fair enough. But see below:


>> I'd never noticed the behaviour of Python where it takes a return value
>> of NotImplemented and raises a ValueError. Unless somebody can tell me
>> why this is justified, I consider this at best a wart. If I return
>> something, that's my return value! I don't see why arithmetic
>> operations are special enough to justify this special behaviour.
> 
> Python Reference Manual, Section 3.2:
> 
> ----
> 
> NotImplemented This type has a single value.  There is a single object
> with this value.  This object is accessed through the built-in name
> NotImplemented.  Numeric methods and rich comparison methods may return
> this value if they do not implement the operation for the operands
> provided.  (The interpreter will then try the reflected operation, or
> some other fallback, depending on the operator.)  Its truth value is
> true.
> 
> ----
> 
> This is exactly the behavior we want.  Our code paths are simpler and
> less error prone if A and B don't both know how to multiply with each
> other, and this seems to be exactly what NotImplemented and
> __mul__/__rmul__ are designed for.

And I argue that they *shouldn't be*. If my code returns some object,
Python shouldn't muck about with it. Making a special case behaviour for
arithmetic is poor design -- arithmetic isn't special enough to justify
the special behaviour.

If you need to trigger a special behaviour (such as "I don't know how to
do this multiplication, please try the other object") the correct way to
do it is with an exception, just as iterators use the StopIteration
exception to trigger special behaviour, or list iteration use IndexError.
Returning a magic value that is captured and handled specially is just
wrong.

Exceptions are more generous too: Python could use your exception's
message string when printing the traceback, instead of making its own.

All of the above is, of course, in my not-so-humble opinion, and none of
it solves your problem. Sorry.


-- 
Steven.




More information about the Python-list mailing list