Behavior of += (was Re: [Python-Dev] Customization docs)

Bengt Richter bokr at oz.net
Wed Jun 5 19:39:12 EDT 2002


On Tue, 4 Jun 2002 08:03:30 -0400, "John Roth" <johnroth at ameritech.net> wrote:

>
>"Huaiyu Zhu" <huaiyu at gauss.almadan.ibm.com> wrote in message
>news:slrnafo7qv.37c.huaiyu at gauss.almadan.ibm.com...
>> Gustavo Cordova <gcordova at hebmex.com> wrote:
>
>>
>> Great explanation!  The problem stems from the fact that the current
>+=
>> operator implements two semantically distinct operations, chosen
>according
>> to some properties of the operands.  This is not unlike the situation
>of the
>> division operator with distinct behaviors on floats and ints.
>
>This is not an issue with '+='. It's an issue with assignment,
>regardless
>of whether it is standalone or combined with some other operation.
>
>And I disagree that assignment implements two distinct operations.
>Assignment always rebinds. Always. In the examples cited, it
Not so fast with that "Always." ;-)

 >>> class P(object):
 ...     def __init__(self,v): self._v = v
 ...     def get_v(self): return self._v
 ...     def set_v(self,v): return # ;-)
 ...     v = property(get_v, set_v)
 ...
 >>> p=P('orig value')
 >>> p.v
 'orig value'
 >>> id(p.v)
 8209984
 >>> p.v = 'try a change'
 >>> id(p.v)
 8209984
 >>> p.v
 'orig value'
 >>> p.v += ' try an increment'
 >>> id(p.v)
 8209984
 >>> p.v
 'orig value'

>attempted to rebind into a tuple, because that's what was asked
>for when the left hand side had a subscript.
>
>The reason that the examples given at the top of the thread fail
>in such strange ways is simply that '+=' does not check whether
>the assignment is possible before doing the addition (or concatination,
>in the specific cases cited.)
>
>To see this, you could try the first example, using explicit '+' and
>'='. I suspect it would fail in exactly the same way, with exactly
>the same side effect.
>
You can make a tuple that is more forgiving, in the spirit of Jeff Epler's
suggestion:

 >>> class T(tuple):
 ...     def __setitem__(self,i,thing):
 ...         if self[i] is thing: return
 ...         raise TypeError,"object doesn't support item assignment of new item"
 ...
 >>> t = T( ([0],) )
 >>> t
 ([0],)
 >>> t[0] += [1]
 >>> t
 ([0, 1],)
 >>> t[0] = t[0] + [2]
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 4, in __setitem__
 TypeError: object doesn't support item assignment of new item

And:

 >>> a=t[0]
 >>> a
 [0, 1]
 >>> a += [2]
 >>> a
 [0, 1, 2]
 >>> t[0] = a
 >>> t
 ([0, 1, 2],)

But:

 >>> a = a + [3]
 >>> a
 [0, 1, 2, 3]
 >>> t[0] = a
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 4, in __setitem__
 TypeError: object doesn't support item assignment of new item

Regards,
Bengt Richter



More information about the Python-list mailing list