inconsistency with += between different types ?

Jonathan Hogg jonathan at onegoodidea.com
Tue Aug 6 13:13:19 EDT 2002


On 6/8/2002 17:16, in article
slrnakvugv.c05.Andreas.Leitgeb at pc7499.gud.siemens.at, "Andreas Leitgeb"
<Andreas.Leitgeb at siemens.at> wrote:

> Huaiyu Zhu <huaiyu at gauss.almadan.ibm.com> wrote:
>> That's what it should be.  Yet it is possible for whoever writes __iadd__ to
>> define it the other way.
> Really ?
> 
> Inside __iadd__ I've got the "self"-parameter:
> If I assign directly to "self", then it won't have any effect outside
>  the method.
> If I assign to self.whatever, I mutate the object in place.
> Is there something I've missed, or does it indeed boil down to
> defining or not defining __ixxx__ ?

The returned value from __iadd__ is assigned to the LHS.

>>> class Foo:
...     def __iadd__( self, other ):
...         print self, other
...         return 'foo'
... 
>>> x = Foo()
>>> x
<__main__.Foo instance at 0x416350>
>>> x += 5
<__main__.Foo instance at 0x416350> 5
>>> x
'foo'
>>> 

Therefore, depending on the way you implement __iadd__ you will get either
re-assignment or mutating (or a horrific combination of the two).

> Also, what characterizes an object to be mutable ?
> Is it the existence or not-existence of mutating methods, or
> is the more behind the scenes of strings,ints and tuples ?

The main thing that characterises a mutable object is whether it can be
mutated ;-)

In general, immutability is used to guarantee certain behaviours. For
example, mutable integers don't really make a whole lot of sense anyway and
making integer objects immutable means they can be shared (all 5s are
references to the same 5 -- see the Flyweight Design Pattern).

But when you don't need to guarantee such behaviour you don't need to worry
particularly about mutability. Most objects in Python are mutable.

>> Consider this table:
>>                 in place         assignment
>>             +---------------+----------------+
>> mutable     |       A       |        B       |
>>             +---------------+----------------+
>> immutable   |       C       |        D       |
>>             +---------------+----------------+
> How I understand it:  (and it looks quite reasonable that way)
> (__iadd__ stands for all the __i...__-methods)
> A: __iadd__ is defined
> B: only __add__ is defined, not __iadd__
> C: hmm, if __iadd__ is defined, then "per definition" the object
>    is not immutable, thus not C :-)
> D: neither __iadd__ nor any other mutating method is defined,
>    but __add__ is.

You can write your own immutable objects (well, mostly) that define
__iadd__. As noted above, you just return a new object, but you will get
this behaviour for free if you just define __add__.

>> Consequently we are seeing frequent questions on this issue.
> If it actually works the way, I now think it does, then it's just
> a lack of clear documentation.

Probably ;-)

Jonathan




More information about the Python-list mailing list