Decimal, __radd__, and custom numeric types...

Nick Craig-Wood nick at craig-wood.com
Tue Mar 1 01:48:03 EST 2005


Blake T. Garretson <blake.garretson at gmail.com> wrote:
>  I'm having some issues with decimal.Decimal objects playing nice with
>  custom data types.  I have my own matrix and rational classes which
>  implement __add__ and __radd__.  They know what to do with Decimal
>  objects and react appropriately.
> 
>  The problem is that they only work with Decimals if the custom type is
>  on the left (and therefore __add__ gets called), but NOT if the Decimal
>  is on the left.  The Decimal immediately throws the usual "TypeError:
>  You can interact Decimal only with int, long or Decimal data types."
>  without even trying my __radd__ method to see if my custom type can
>  handle Decimals.
> 
> From the Python docs (specifically sections 3.3.7 and 3.3.8), I thought
>  that the left object should try its own __add__, and if it doesn't know
>  what to do, THEN try the right object's __radd__ method.  I guess
>  Decimal objects don't do this?  Is there a way to change this behavior?
>   If Decimal objects prematurely throw a TypeError before trying the
>  __rop__, is Decimal broken, or was it designed this way?  I think I'm
>  missing something...

It looks like from reading 3.3.8 if decimal raised a NotImplemented
exception instead of a TypeError then it would work.

    For objects x and y, first x.__op__(y) is tried. If this is not
    implemented or returns NotImplemented, y.__rop__(x) is tried. If
    this is also not implemented or returns NotImplemented, a
    TypeError exception is raised. But see the following exception:

    Exception to the previous item: if the left operand is an instance
    of a built-in type or a new-style class, and the right operand is
    an instance of a proper subclass of that type or class, the right
    operand's __rop__() method is tried before the left operand's
    __op__() method. This is done so that a subclass can completely
    override binary operators. Otherwise, the left operand's __op__
    method would always accept the right operand: when an instance of
    a given class is expected, an instance of a subclass of that class
    is always acceptable.

You could try this with a local copy of decimal.py since it is
written in Python.

-- 
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick



More information about the Python-list mailing list