Augmented Assignement (was: Re: PEP scepticism)

Alex Martelli aleaxit at
Mon Jul 2 11:49:53 EDT 2001

"Paul Prescod" <paulp at> wrote in message
news:mailman.994083124.18397.python-list at
> I'd like to see some real-world code that takes advantage of the fact
> that this single operator behaves differently with mutable and immutable
> types. Then I will believe that it isn't just a squishing together of
> two unrelated features.

Depending on how you define "real world", I have some use of that
with my still-unreleased "in-house" (literally:-) "gmpy 1.0", where I
have mutable numbers.  My application code is doing combinatorial
arithmetic (computing bridge-related stuff) -- iterating over a
zillion different possible cases (exhaustively covering all
possible distribution of cards over suits in a given situation),
and for each given case X that occurs n times finding out how case
X is to be classified (e.g., number of tricks that in case X are
taken with playstrategies a/b/c, being compared).  When it's
found the classification index of case X is Y, it just does
    countof[Y] += n

If container countof has been initialized with plain longs (or
standard GMPY mpz's), that's like countof[Y] = countof[Y] + n.

Sometimes these are LONG longs (combinatorial arithmetic does
have a knack for producing *big* numbers... unless you do very
clever analysis indeed to ensure against double- and triple-
counting, and part of this application is exactly eschewing all
the usual clever analysis, that one often gets subtly wrong,
and using brute-force counting from first principles instead).

So, I think releasing the old long (or gmpy.mpz) and allocating
a new incremented one may sometimes be costly.  But anyway this
is what I get to have with good-old-Python, and with the gmpy
that is released (because I accepted the unanimous advice from
all Pythonistas who deigned to comment -- numbers must stay
immutable).  With the "new and improved" gmpy, I have an mpz
variant that is mutable.  So if I initialize countof with such
numbers, I'll get inplace incrementing and save the deallocation
and reallocation cost at each and every increment.  Nothing
huge I guess, these ARE scalars after all albeit big ones at
times, but over a few million increments it builds up a bit.

Having this polymorphism here lets me write an application that
can run in plain Python, or with released-gmpy (a bit faster,
because I get to use GMP's enhanced algorithms for long int
[mpz] multiplication, the fast builtin 'comb' function, &c),
or with experimental-gmpy (a bit faster yet).  I like this.
I do want to keep the flexibility because one day this might
be running in Jython (e.g. as part of some JSP setup on the
net) or under a Python installation I don't fully control
(e.g. at some ISP's) so I may or may not be able to install
gmpy on the side, or I may only be able to install the fully
stable, released version.

Of course, except for performance, I couldn't care less
whether the increment is inplace or not -- I never have
other outstanding references to the 'bins' of countof as
I run this nested loop, so the identity of the object that
the bin references is of no interest here.

I guess that's pretty much a limit case for += &c on *scalars*.

Most scalars probably won't have significant costs in
freeing and allocation -- huge integer or rational numbers
would seem to be atypical this way; surely vectors/matrices
will be involved most of the time that +='s inplace version
does matter performance-wise.  But I doubt I'm the only
weirdo doing combinatorial arithmetic, though most may be
currently suffering from the 'numbers must be immutable'
taboo and not considering 'mutable numbers' as a possible
source of speedup:-).


More information about the Python-list mailing list