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

Tim Hochberg tim.hochberg at ieee.org
Wed Mar 29 17:45:10 CEST 2006

Armin Rigo wrote:
> Hi Greg,
> On Wed, Mar 29, 2006 at 12:38:55PM +1200, Greg Ewing wrote:
>>I'm really thinking more about the non-inplace operators.
>>If nb_add and sq_concat are collapsed into a single slot,
>>it seems to me that if you do
>>   a = [1, 2, 3]
>>   b = array([4, 5, 6])
>>   c = a + b
>>then a will be asked "Please add yourself to b", and a
>>will say "Okay, I know how to do that!" and promptly
>>concatenate itself with b.
> No: there is a difference between + and += for lists.  You can only
> concatenate exactly a list to a list.  Indeed:
>    >>> [].__add__((2, 3))
>    TypeError: can only concatenate list (not "tuple") to list
> By contrast, list += is like extend() and accepts any iterable.
> So if we provide a complete fix, [].__add__(x) will be modified to
> return NotImplemented instead of raising TypeError if x is not a list,
> and then [1,2,3]+array([4,5,6]) will fall back to array.__radd__() as
> before.

Ouch. Assuming the same path is followed with tuples, I think that this 
means the following behaviour will continue:

 >>> t = (1,2,3)
 >>> a = array([4,5,6])
 >>> t += a
 >>> t
array([5, 7, 9])

That's not particularly desirable. There's not much to be done about it 
short of adding __iadd__s everywhere, which is probably brittle and 
unfriendly. And, admittedly this is a corner case that's very rarely 
going to cause trouble. Still, perhaps for Py3K it's worth considering 
if PyNumber_InplaceAdd should only call __iadd__ and __add__, not 
__radd__. Thus giving the target object complete control during inplace 
adds. Similarly for other inplace operations, of course.

I'm not certain that all of the consequences of this change would be 
benign, but it's something to consider.

> I'll try harder to see if there is a reasonable example whose behavior
> would change...


Tim Hochberg

More information about the Python-Dev mailing list