[PEP 203] Augmented Assignment

Tim Hochberg tim.hochberg at ieee.org
Mon Aug 14 21:57:49 EDT 2000


[Thomas Wouters explains to Frank Niessink why we don't need no
steeenking hooks for "regular assignment"]

This reminds of something I long ago though would be nice to have for
NumPy; since once of the driving forces behind augmented assigments is
things like NumPy, I think I'll toss it out for comment even though I
have not thought it all the way through.

Consider the expression:

e = a * b * c * d

where a, b, c, and d are large, square matrices. This ends up
allocating space for 3 extra matrices.  This can be reduced further at
the expense of extra lines of code, but because matrices don't commute
in general its harder to do using the mechanisms in the PEP than one
might think.

One solution that was considered at one point was to defer evaluation
the math operators. So, a*b would produce a MatrixExpression object
and at some point this MatrixExpression would be evaluated to to yield
a real array. With current Python this has several problems all
related to when to evaluate the expression. One strategy is that one
waits till the first value is asked for, then the array is evaluated:

e = a*b*c*d
print e[0] # d evaluated now.

But one now has an extra (psuedo) array type floating around and tests
such as "if type(a) == ArrayType" don't work as expected. Also, the
difficulty in predicting when a big calculation would be performed
might be a problem for people working on interactive programs. Another
tack would be to explicitly evaluate the expressions:

e = ((a*b*c)*d).evaluate()

But that would be cumbersome in error prone in real life.

So, back to the PEP:

Suppose we add a hook for regular assigment. I'll call it __becomes__
after the "and becomes" in __XXX_ab__. When the object spam is
assigned the name "eggs" (eggs = spam) a check is made for the
existence of a __becomes__ method. If one is present the result of
spam.__becomes__() is assigned the name "eggs", not the object spam
itself. To go back to our original example:

e = a*b*c*d

This would create a MatrixExpression that holds the deferred
evaluation of a*b*c*d. Then, MatrixExpression.__becomes__() would be
called and the resulting array assigned the name e. Only one matrix would
have been allocated assuming the implementation of MatrixExpression is
sufficiently clever. (In this case, __becomes__ would be the same as
__evaluate__ in the previous example).

This probably has all kinds of potential for abuse. And I haven't
thought it through all the way, but I figured I'd throw it out for
discussion.

-tim



More information about the Python-list mailing list