[Python-ideas] Reverse assignment operators (=+, =-, =*, =/, =//, =**, =%)

Nick Timkovich prometheus235 at gmail.com
Mon Nov 14 13:57:36 EST 2016


Currently, Numpy takes advantage of __iadd__ and friends by performing the
operation in-place; there is no copying or other object created. Numpy is
very thinly C, for better and worse (which is also likely where the +=
syntax came from). If you're doing vast amounts of numeric computation, it
quickly pays off to learn a little about how C likes to store arrays in
memory and that doing things like creating a whole new array of the same
size and having to free up the old one for every operation isn't a great
idea. I strongly dislike the notion that I'd have to use arbitrary function
calls to add one to an entire array, or multiply it by 2, or add it to
another array, etc.

As a minor nit, np.vectorize doesn't make in-place functions, it simply
makes a naive, element-wise function act as though it was vectorized. The
name is unfortunate, because it does nothing to speed it up, and it usually
slows it down (because of that layer). Reworking code to avoid copying
large arrays by doing in-place operations is the preferred method, though
not always possible.

Nick

On Mon, Nov 14, 2016 at 12:21 PM, Mikhail V <mikhailwas at gmail.com> wrote:

> On 14 November 2016 at 12:16, Steven D'Aprano <steve at pearwood.info> wrote:
> > On Mon, Nov 14, 2016 at 01:19:30AM +0100, Mikhail V wrote:
> >
> > [...]
> >> >> A good syntax example:
> >> >>
> >> >> a = sum (a, c)
> >
> > There is a reason why mathematicians and accountants use symbols as a
> > compact notation for common functions, instead of purely functional
> > notation.
> >
> > Here is a real-world example, the formula for compound interest:
> >
> > A = P*(1+r/100)**n
> >
> > Compare that to:
> >
> > A = mul(P, pow(sum(1, div(r, 100)), n))
> >
> > Even Reverse Polish Notation is easier to read than that series of
> > functions:
> >
> > P 1 r 100 / + n ** *
> >
> >
> > Don't misunderstand me, functions are important, and over-use of cryptic
> > symbols that are only meaningful to an expert will hurt readability and
> > maintainability of code. But people have needed to do arithmetic for
> > over six thousand years, and there is no good substitute for compact
> > operators for basic operations.
>
> I agree. Actually I meant that both are good examples.
> In some cases I still find function-style better, so this:
>
> A = P*(1+r/100)**n
>
> I would tend to write it like:
>
> A = P * pow((1 + r/100) , n)
>
> For me it is slightly more readable, since ** already makes the
> equation inconsistent.
> And of course you cannot use glyphs for all possible operations, it
> will be total mess.
>
> Most of problems with function-style equations come from limitations
> of representation
> so for Courier font for examples the brackets are too small and makes
> it hard to read.
> With good font and rendering there no such problems. Some equation editors
> allow even different sized brackets - the outer extend more and more
> when I add nested equations, so it looks way better.
>
>
> > [...]
> >> It is kind of clear from the context, that I am speaking of syntax and
> >> not how things are working under the hood, or?
> >> If a compiler cannot optimize "a = a + 1" into an in-place operation,
> >> that is misfortune.
> >
> > That's not how Python works. Or at least, not without an extremely
> > powerful and smart compiler, like PyPy.
> >
> > In Python, integers (and floats) are immutable objects. They have to be
> > immutable, otherwise you would have things like this:
> >
> > x = 1
> > y = x
> > x = x + 1  # changes the object 1 in place
> > print(y*10)  # expect 10, but get 20
> >
> > That's how lists work, because they are mutable:
> >
> > py> x = [1]
> > py> y = x
> > py> x[0] = x[0] + 1
> > py> print(y[0]*10)  # expect 1*10 = 10
> > 20
> >
> >
> > A "sufficiently smart" compiler can work around this, as PyPy does under
> > some circumstances, but you shouldn't expect this optimization to be
> > simple.
> >
> > [...]
> >> A better option would be to support unary operators so the user
> >> can write directly without assignment:
> >>
> >> inc (a, 1)
> >>
> >> Would mean in-place increment "a" with 1
> >
> > That is impossible with Python's executation model, in particular the
> > "pass by object sharing" calling convention. I expect that this would
> > require some extremely big changes to the way the compiler works,
> > possibly a complete re-design, in order to allow pass by reference
> > semantics.
>
> Thanks a lot for a great explanation!
> So for current Python behavior, writing
>
> x = x + 1
>
> and
>
> x += 1
>
> Would mean the same in runtime? Namely creates a copy and assigns
> the value  x+1  to x. Or there is still some overhead at parsing stage?
> Then however I see even less sense in using such a shortcut,
> it would be good to dismiss this notation, since it makes hard
> to read the code.
> As for Numpy, it uses anyway its own approaches, so
> in-place should use own syntax, e.g. like numpy.sum(x_, a) to
> do it in-place.
>
>
> Mikhail
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20161114/538d5077/attachment-0001.html>


More information about the Python-ideas mailing list