Relax Syntax for Augmented Arithmetic?

Mark Wooding mdw at distorted.org.uk
Mon Jan 19 21:32:28 EST 2009


Steven D'Aprano <steven at REMOVE.THIS.cybersource.com.au> writes:

> There's a practical reason too. You create a new Foo instance, mutate
> it with the augmented assignment operator, and then a tenth of a
> millisecond later the garbage collector throws it away because it has
> a reference count of zero.

Only in this specific example.  A function can easily return a
well-known object, which it's sensible to mutate.

Besides,

        class mumble (object): pass
        mumble().foo = 1

is accepted without fuss, and is just as useless.

I think I see the confusion here.

  * Python assignment (`=') is fairly simple.  The left-hand side is
    analyzed syntactically: if it's a plain name then the variable it
    denotes is modified; otherwise an appropriate method is invoked to
    mutate some object.

  * Python augmented-assignment (`+=', for example) is inconsistent.
    Depending on what type of object the left-hand side evaluates to, it
    may /either/ mutate that object, /or/ assign a new value to the
    expression.

What do I mean?  Well, consider this function.

        def assg(x, y):
          x = y

Under no circumstances does calling this function have any effect (other
than wasting time and memory).  But:

        def aug(x, y):
          x += y

Calling this function might or might not have an observable effect,
depending on the type of x.  For example,

        x = 5
        aug(x, 3)

is useless, but

        x = [1, 2, 3]
        aug(x, [4])

is not.

The `aug' function can be used to bypass the syntactic restriction on
augmented assignment, where it makes sense:

  aug(func(), 17)

is always syntactically valid, and may or may not be useless depending
on the type of thing returned by `func'.

The Python language refuses to let the programmer write something which
is (a) possibly meaningful, and (b) possibly useful because augmented
assignment inherits the syntactic restriction of simple assignment that
the left-hand side expression designate a `place' -- i.e., one of the
things that there's a rule for assigning to, e.g., VAR, EXPR[INDEX],
EXPR.ID -- because it /might/ need to perform such an assignment, though
it might not.

My personal view is that augmented-assignment operators which work by
mutation rather than assignment (e.g., `+=' on lists, rather than `+='
on numbers) are one of Python's least pleasant warts.  But if they're
going to exist then I think

        list() += [1]

ought to be valid syntax, since semantically it's actually clear what it
should do (namely, construct a fresh empty list, append a `1' to it, and
then throw the whole thing away).  Of course,

        tuple() += 1,

is still meaningless, and ought to be an error.  Of course, this removes
a static error-check, but if we were petty about getting all our errors
at compile time we wouldn't be writing in Python in the first place.

-- [mdw]



More information about the Python-list mailing list