[Python-Dev] behavior of inplace operations

Guido van Rossum guido@python.org
Tue, 11 Jun 2002 22:06:42 -0400

> My initial post asking about the implementation of += sparked a
> small thread over on python-list, from which I've come to the
> conclusion that my little optimization suggestion (don't try to set
> the attribute or item if the inplace op returns its first argument)
> is actually more semantically correct.
> Thoughts?

One problem is that it's really hard to design the bytecode so that
this can be implemented.  The problem is that the compiler sees this:

   a[i] += x

and must compile bytecode that works for all cases: a can be mutable
or immutable, and += could return the same or a different object as
a[i].  It currently generates code that uses a STORE_SUBSCR opcode
(store into a[i]) with the saved value of the object and index used
for the BINARY_SUBSCR (load from a[i]) opcode.  It would have to
generate additional code to (a) save the object retrieved from a[i],
(b) compare the result to it using the 'is' operator, and (c) pop some
stuff of the stack and skip over the assignment if true.  That could
be done, but the extra test would definitely slow things down.

A worse problem is that it's a semantic change.  For example,
persistent objects in Zope require (under certain circumstances) that
if you modify an object that lives in a persistent container, you have
to store it back into the container in order for the persistency
mechanism to pick up on the change.  Currently we can rely on a[i]+=x
and a.foo+=x to do the assigment.  Under your proposal, we couldn't
(unless we knew that the item was of an immutable type).  That is such
a subtle change in semantics that I don't want to risk it without
years of transitional warnings.

Personally, I'd rather accept that if you have a = ([], [], []),
a[1]+=[2] won't work.  You can always write a[1].extend([2]).

--Guido van Rossum (home page: http://www.python.org/~guido/)