From: Steven D'Aprano on
I'm reading the source code for decimal.Decimal, and I see that the
arithmetic operations (__add__, __sub__, etc.) start with code like this:

if other is NotImplemented:
return other


I don't understand the purpose of this. I presume that it is *not* for
the use-case of:

d = Decimal('123.456')
result = d + NotImplemented

which not only doesn't make sense to me, but when I try it, it raises
TypeError. So I find myself confused why the arithmetic methods do this.



--
Steven
From: Kushal Kumaran on
On Sat, Apr 24, 2010 at 8:54 AM, Steven D'Aprano
<steve(a)remove-this-cybersource.com.au> wrote:
> I'm reading the source code for decimal.Decimal, and I see that the
> arithmetic operations (__add__, __sub__, etc.) start with code like this:
>
>        if other is NotImplemented:
>            return other
>
>
> I don't understand the purpose of this. I presume that it is *not* for
> the use-case of:
>
> d = Decimal('123.456')
> result = d + NotImplemented
>
> which not only doesn't make sense to me, but when I try it, it raises
> TypeError. So I find myself confused why the arithmetic methods do this.
>

There's a _convert_other method which is called before the test that
can return NotImplemented.

--
regards,
kushal
From: Steven D'Aprano on
On Sat, 24 Apr 2010 09:05:14 +0530, Kushal Kumaran wrote:

> On Sat, Apr 24, 2010 at 8:54 AM, Steven D'Aprano
> <steve(a)remove-this-cybersource.com.au> wrote:
>> I'm reading the source code for decimal.Decimal, and I see that the
>> arithmetic operations (__add__, __sub__, etc.) start with code like
>> this:
>>
>>        if other is NotImplemented:
>>            return other
>>
>>
>> I don't understand the purpose of this. I presume that it is *not* for
>> the use-case of:
>>
>> d = Decimal('123.456')
>> result = d + NotImplemented
>>
>> which not only doesn't make sense to me, but when I try it, it raises
>> TypeError. So I find myself confused why the arithmetic methods do
>> this.
>>
>>
> There's a _convert_other method which is called before the test that can
> return NotImplemented.


Yes, I can see that, but why?



--
Steven
From: Chris Rebert on
On Fri, Apr 23, 2010 at 11:25 PM, Steven D'Aprano
<steve(a)remove-this-cybersource.com.au> wrote:
> On Sat, 24 Apr 2010 09:05:14 +0530, Kushal Kumaran wrote:
>> On Sat, Apr 24, 2010 at 8:54 AM, Steven D'Aprano
>> <steve(a)remove-this-cybersource.com.au> wrote:
>>> I'm reading the source code for decimal.Decimal, and I see that the
>>> arithmetic operations (__add__, __sub__, etc.) start with code like
>>> this:
>>>
>>>        if other is NotImplemented:
>>>            return other
>>>
>>>
>>> I don't understand the purpose of this. I presume that it is *not* for
>>> the use-case of:
>>>
>>> d = Decimal('123.456')
>>> result = d + NotImplemented
>>>
>>> which not only doesn't make sense to me, but when I try it, it raises
>>> TypeError. So I find myself confused why the arithmetic methods do
>>> this.
>>>
>> There's a _convert_other method which is called before the test that can
>> return NotImplemented.
>
> Yes, I can see that, but why?

If the conversion to Decimal in _convert_other() fails, the operator
method returns NotImplemented to signal to the interpreter that
Decimal doesn't know how to do the requested operation with an operand
of the given type; the interpreter will fall back by calling the
reflected method of the other operand. And if that also fails, the
interpreter raises TypeError:
>>> Decimal(4)+'g'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Decimal' and 'str'

Note how the traceback doesn't mention decimal.py

See also NotImplemented's entry in the docs:
http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy

Now, they could have had _convert_other() return some other sentinel
value (or raise an exception) to indicate that the conversion failed,
but they didn't; it probably made the code marginally simpler.

Cheers,
Chris
--
http://blog.rebertia.com
From: Steven D'Aprano on
On Fri, 23 Apr 2010 23:51:39 -0700, Chris Rebert wrote:

> If the conversion to Decimal in _convert_other() fails, the operator
> method returns NotImplemented to signal to the interpreter that Decimal
> doesn't know how to do the requested operation with an operand of the
> given type; the interpreter will fall back by calling the reflected
> method of the other operand.

I knew that works with comparisons __eq__ etc, but somehow I had a mental
blank about arithmetic operators! Yes, you're right, and the docs say so
explicitly. Somehow I had convinced myself that NotImplemented only
worked with comparisons.


--
Steven