[Python-Dev] PEP 203 Augmented Assignment

Thomas Wouters thomas@xs4all.net
Thu, 27 Jul 2000 11:06:23 +0200


On Thu, Jul 27, 2000 at 12:59:15AM -0500, Guido van Rossum wrote:

> I'm making up opcodes -- the different variants of LOAD and STORE
> don't matter.  On the right I'm displaying the stack contents after
> execution of the opcode (push appends to the end).  I'm writing
> 'result' to indicate the result of the += operator.

I take it you rather see a 'AUGOP' bytecode than a 'GETSET_<type>' bytecode,
that does the loading, operation and storing ? Not that I disagree, not at
all, I just want to have that clear ;)

> There are two more forms of potential interest.  First, what should
> happen to a tuple assignment?
> 
>   a, b, c += x
> 
> (Which is exactly the same as "(a, b, c) += x".)

Here's what happens now:

>>> (a, b, c) += 1,2,3
SyntaxError: no augmented assignment to tuple

(Isn't a reference implementation a cool thing ? ;)

> Second, what should happen to a slice assignment?  The basic slice
> form is:

>   a[i:j] += b

> but there are others: Python's slice syntax allows an arbitrary [yadah]

What's so special about slice assignment ? You yourself (though Tim<wink>)
suggested the following:

x += y

is effectively (minus order and number of evaluations)

x = x.__add_ab__(y)

Where __add_ab__() is the Python method, if 'x' is a python class, or plain
'__add__' if 'x' doesn't have an '__add_ab__', or 'y.__radd__' if x doesn't
have __add__. Similarly, if 'x' is a builtin, tp_as_number->nb_inplace_add is
used, or tp_as_number->nb_add, etc. (Or sq_concat, if it's a seq and the
operator is add.)

The __add_ab__ method, or the C equivalent, can decide for itself whether it
should return 'self', thus making the operation truly in-place, or a new
instance of an object. This may seem as a complicated and unexpected way to
do things, but it makes it possible to transparently support __add__ and
__radd__ too, because they already return new objects.

And you (through Tim) literally scolded me for trying to suggest

x[1:10] += y

being something like

x = x.__add_slice_ab__(y, slice(1,10))

Instead, it should become

x[1:10] = x[1:10] + y

(Or rather, to keep the same order of evaluation:)

tmp1 = y # in case of a more complicated expression
tmp2 = x[1:10]
x[1:10] = tmp2.__add_ab__(tmp1)

The whole story about how complicated, convoluted and confusing Python's
slicing is, though interesting and correct, is not connected to augmented
assignment ;) 

>   a[:, ..., ::, 0:10:2, :10:, 1, 2:, ::-1] += 1

Becomes

tmp1 = a[:, ..., ::, 0:10:2, :10:, 1, 2:, ::-1]
a[:, ..., ::, 0:10:2, :10:, 1, 2:, ::-1] = tmp1.__add_ab__(1)

> It would be nice if the SLICE bytecodes were removed altogether and
> instead slice() objects would be created for all slices, even basic
> ones.  (I believe this was proposed in this list at some point.)  The
> original SLICE opcodes were introduced in ancient times, when basic
> slices were the only accepted slice syntax.

Agreed, however! You can't just make all slices use a sliceobject, for two
reasons: a C extention type can use both the sequence and the mapping
interface, and might not expect basic slices to be turned into a slice
object. For instance, it's mapping interface may raise a TypeError, "Slices
not supported", when it encounters a slice. Choosing mapping over sequence
methods may break all that code. The same goes for Python classes.

The other reason is usability. The current __get_slice__(self, start, end)
sytnax is very convenient for nearly all uses of slices. Possibly because
the builtin types don't handle extended slices currently, and possibly
because the slice-object way is not generally known. (Just recently, there
was someone asking on python-list on how to use slices. I'm not sure if he
got a proper answer, but I've never seen such questions on the subject of
basic slices!)

If we do get a new __get_slice__ that handles all slices, I suggest doing it
like this:

class X:
    def __get_newslice__(self, (start, end, step)):

where the type of start, end and step is not defined. This can be done with
slice objects and sequence-unpacking, of course, but it makes it a lot more
usable.

Back-to-my-meetings-ly y'rs,

-- 
Thomas Wouters <thomas@xs4all.net>

Hi! I'm a .signature virus! copy me into your .signature file to help me spread!