new-style classes multiplication error message isn't very informative

ziga.seilnacht at gmail.com ziga.seilnacht at gmail.com
Fri Dec 30 09:01:35 EST 2005


Jon Guyer wrote:
> >>> This is a fake line to confuse the stupid top-posting filter at gmane
>
> 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:
>
>     >>> class my:
>     ...     def __mul__(self, other):
>     ...             return NotImplemented
>     ...
>     >>> my() * my()
>     Traceback (most recent call last):
>       File "<stdin>", line 1, in ?
>     TypeError: unsupported operand type(s) for *: 'instance' and 'instance'
>
> This error message isn't hugely meaningful to many of our users (and in
> complicated expressions, I'd certainly benefit from knowing exactly which
> subclasses of 'my' are involved), but it beats the behavior with new-style
> classes:
>
>     >>> class my(object):
>     ...     def __mul__(self, other):
>     ...             return NotImplemented
>     ...
>     >>> my() * my()
>     Traceback (most recent call last):
>       File "<stdin>", line 1, in ?
>     TypeError: can't multiply sequence to non-int
>
> After a lot of googling and a lot of pouring over abstract.c, I now
> understand that object() is defined with a tp_as_sequence, and so the error
> message is the result of the last-ditch effort to do sequence concatentation.
>
> What if I don't want to permit sequence concatenation?
> Is there a way to unset tp_as_sequence?
> Should I be inheriting from a different class?  We started inheriting from
> object because we want a __new__ method.
>
> The "'instance' and 'instance'" message would be OK, but even better is the
> result of this completely degenerate class:
>
>     >>> class my(object):
>     ...     pass
>     ...
>     >>> class your(my):
>     ...     pass
>     ...
>     >>> my() * your()
>     Traceback (most recent call last):
>       File "<stdin>", line 1, in ?
>     TypeError: unsupported operand type(s) for *: 'my' and 'your'
>
> That's an error message I can actually do something with.  Is there any way
> to get this behavior when I do have a __mul__ method and sometimes return
> NotImplemented?
>
> We're doing most of our development in Python 2.3, if it matters.

This is a bug in Python. See this thread:
http://mail.python.org/pipermail/python-dev/2005-December/059046.html

and this patch:
http://sourceforge.net/tracker/?group_id=5470&atid=305470&func=detail&aid=1390657

for more details.




More information about the Python-list mailing list