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

Huaiyu Zhu huaiyu at gauss.almadan.ibm.com
Tue Jun 4 21:06:42 EDT 2002


[Huaiyu Zhu]
> This is not unlike the situation of the
> division operator with distinct behaviors on floats and ints.

[Chris Barker]
I suppose that is a pretty good parallel, but not quite the same, as the
behavior of += is much more similar for the different types ...

[Huaiyu Zhu]
In fact, the behavior of += is even more different in different situations.
Integer division sometimes equals real division, but modification in an
object is never the same as modification in namespace.  In-place
modification affects all names referencing the same object, as the following
example shows

[Steve Holden]
>>> a = b = (1, 2, 3)
>>> a += ('boo!',)
>>> a, b
((1, 2, 3, 'boo!'), (1, 2, 3))
>>> a = b = [1, 2, 3]
>>> a += ['boo!']
>>> a, b
([1, 2, 3, 'boo!'], [1, 2, 3, 'boo!'])

[Donn Cave]
Well, it is consistent.  Maybe not in a way that you can see
and still remain sane.  "Mutable" or not, it must always work
like "a = iadd(a, b)", where iadd attempts to perform some
computation like __iadd__() or eventually "+".  

[Huaiyu Zhu]
That "must" is only an artifact of trying to incorporate rebinding increment
for the sake of immutables.  It is similar to that / "must" return an integer
for integer oprerands.

[Huaiyu Zhu]
It is interesting to spell out the analogy with integer division:

- Real division is not well defined for integers (if result must be integer).
- Integer division is a useful approximation that works for intergers.
- Integer division is also meaningful for reals, but it is different from
  real division.
- Python uses the same symbol / for both operations depending on operarands,
  causing quite some inconsistency and confusion.
- The solution is to use / for real division only, while introducing another
  operator // for integer division.

- In-place increment is not well defined for immutables.
- Rebinding increment is a useful approximation that works for immutables.
- Rebinding increment is also meaningful for mutables, but it is different from
  in-place increment.
- Python uses the same symbol += for both operations depending on operands,
  causing quite some inconsistency and confusion.
- The solution might be to use += for inplace increament only, while
  introducing another operator (?) for rebinding increment.

Chris Barker gave details of several kinds of inconsistencies.

[Donn Cave]
Not really - the current semantics are actually better than the fixed
version, inasmuch as they are at least consistent.  As I interpret the
proposal, the fixed += would sometimes work without rebinding (if the
object supports it) and sometimes would be an assignment (falling back
to +.)  To me, to allow an object to dictate its relationship to its
computational environment like that is anathema.

[Huaiyu Zhu]
That is one proposal.  My proposal is to disallow += for immutables.
Another symbol would be used for rebinding operations.  (Or maybe swap the
role of these symbols.)  Thus for mutables both operations would be
available.  No, 'a=a+b' is not enough for rebinding, as the following shows:

[Bengt Richter]
 >>> foo()[0]+=1
 side effect
 >>> foo()[0] = foo()[0]+1
 side effect
 side effect


Huaiyu



More information about the Python-list mailing list