[Python-Dev] INPLACE_ADD and INPLACE_MULTIPLY oddities in ceval.c

Travis E. Oliphant oliphant.travis at ieee.org
Tue Mar 28 05:10:10 CEST 2006


Guido van Rossum wrote:
> On 3/27/06, Travis Oliphant <oliphant.travis at ieee.org> wrote:
>> If you have Numeric or numpy installed try this:
>>
>> #import Numeric as N
>> import numpy as N
>>
>> a = range(10)
>> b = N.arange(10)
>>
>> a.__iadd__(b)
>>
>> print a
>>
>> Result:
>>
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>
>>
>> Contrast the returned output with
>>
>> import numpy as N
>>
>> a = range(10)
>> b = N.arange(10)
>>
>> a += b
>>
>> print a
>>
>> Result:
>>
>> [ 0  2  4  6  8 10 12 14 16 18]
>>
>>
>> Having "a+=b" and "a.__iadd__(b)" do different things seems like an
>> unfortunate bug.
>>
>> It seems to me that the problem is that the INPLACE_ADD and
>> INPLACE_MULTIPLY cases in ceval.c  use PyNumber_InPlace<YYY> instead of
>> trying PySequence_InPlace<YYY> when the object doesn't support the
>> in-place number protocol.
>>
>> I could submit a patch if there is agreement that this is a problem.
> 
> Well how is the interpreter to know whether += meanse numeric add or
> sequence add in any particular case?
>

I can see that '+' (and '*') having two different implementation slots 
is a design bug.  However, it seems prudent that both += and .__iadd__ 
should have identical behavior regardless.  Whatever mechanism is used 
to resolve the conflict for __iadd__, the same mechanism should be used 
for for +=.

I don't think this is a NumPy-only issue.  Any object that defines 
addition that works with lists will have similar problems.

I think this can be fixed easily by first checking the sequence slot for 
a sq_concat function before calling PyNumber_InPlaceAdd.

All I'm asking for is that a += b  have the same behavior as 
a.__iadd__(b).   That seems like desireable behavior to me.

-Travis



More information about the Python-Dev mailing list