inconsistency with += between different types ?

Huaiyu Zhu huaiyu at gauss.almadan.ibm.com
Wed Aug 7 21:15:48 CEST 2002


Christopher A. Craig <list-python at ccraig.org> wrote:
>Andreas.Leitgeb at siemens.at (Andreas Leitgeb) writes:
>
>> This of course explains, why it causes that much trouble.
>> A possible path to change this situation might be as follows: 
>> (Although I feel too new at Python to actually propose a change :-)
>>   Automatically treat a None returnvalue from an __ixxx__-method as self
>>   Issue a Warning, if __ixxx__ returns anything else than self or None
>>   Ignore the return-value altogether.
>> Each of these steps might have to wait for a major-version-step in
>> Python.
>> This would make sure that clean implementations would stay ok, while
>> those implementations, that obfuscate the design of <op>= will hopefully
>> phase out.
>
>You do realize that at the end of this += would only apply to lists
>and would be exactly identical to list.append(), right?  Because ints,
>longs, floats, tuples, and in the future rationals are all immutable
>and thus cannot return self.

Why would they want to define __iadd__ then?  If they don't define __iadd__,
they get the x=x+y behavior from x+=y automatically.  Try to define a class
with __add__ but without __iadd__ and use id() to see for yourself.

>As an example:
>>>> a=t=6
>>>> a2=t2=[1,2,3]
>>>> t+=5
>>>> t2+=[5]
>>>> a==t
>0
>>>> a2==t2
>1
>
>So your proposed change would make augmented assignment fail on all
>numeric types.  That seems a rather bad choice to me.  

This is not true.  There are two confusing things about the current +=
implementation.

(1) it allows immutable objects to get x=x+y semantics automatically.

(2) it allows classes to define __iadd__ with a semantics that is neither
    in-place, nor equiv to (1) above.  In particular, if you forget return,
    you get this behavior.

The second is a nasty behavior without much practical value.  What Andreas
proposed only removes (2), while leaving (1) intact.  Even if you strongly
advocate retaining (1) for pragmatical reasons, IMHO you should still
support removing (2), simply for the reason of making (1) much less
confusing to use.

Once that's done, the documentation could be as simple as:

  If __iadd__ is defined, x+=y changes x in place as per x.__iadd__(y).
  Otherwise x+=y has a semantics similar x=x+y, except that x is only
  evaluated once.

In contrast, I'd challenge anyone to explain the current += behavior in less
than twice that many words without misleading casual readers.

I'd also like to see anyone showing real use for the behavior (2).

The fact that more than half of the posters in this thread did not realize
that (2) is a possible behavior and is different from (1) demonstrates how
counter-intuitive (2) really is.

Huaiyu



More information about the Python-list mailing list