Understanding Python's augmented assignment (a += b)
stupidpythonideas.blogspot.com
stupidpythonideas.blogspot.com
https://mail.python.org/pipermail/python-dev/2014-March/1331...
(the PEP author posts a couple messages in the thread too)
std::vector<int> t = {0, 1};
t[0] calls operator[], which returns an int&. This is precisely an lvalue reference, which is kind of like a memory address, but int& is a type in its own right. Calling it a "reference object" is not entirely correct, but it's also not entirely incorrect. And let's not get started on vector<bool>...It all stems from the different behaviour of = in Python and C++ - in Python = binds the name on the left to the value on the right and you can have any number of names for a value; in C++ each name is exactly one value (even in the case of references - the reference itself is a pointer and there's no other name that signifies the memory in which that pointer value is stored) and = copies the value from the thing on the right to the thing on the left, in a way determined by the thing on the left (so for references the value is copied to the thing that the reference points to and other types can override operator= to do whatever they like), but the base concept is that = copies a value from one place to another (or moves it if it's an xvalue and you're using C++11 and what's on the left implements move-assignment).
P.S. Since C++ lets you do as you like, you can for instance implement operator[](size_t, const T&) as assignment and then t[0, 2] will assign 2 to t[0]. Try putting
template <class T>
void operator[](T* p, size_t i, const T& v) { p[i] = v; }
in a header file in your next project for fun. Then use t[i, v] for all your array assignments. >>> _tmp = getitem(t, 0)
>>> setitem(t, 0, _tmp)
>>> try:
>>> _tmp2 = _tmp.__iadd__([2])
>>> except AttributeError:
>>> _tmp2 = _tmp.__add__([2])
>>> setitem(t, 0, _tmp2)
Then if the first setitem raises, the rest of the code will be skipped. Obviously this isn't perfect:1. If setitem has strange side-effects, this will cause them to happen twice. 2. If setitem raises based on the value (rather than the key), this won't notice that.
But otherwise, it seems like a pretty straightforward improvement, no?
>>> import numpy
>>> x=0
>>> y=numpy.int32(2*10**9)
>>> x+=y
>>> x+=y
>>> x
-294967296
In later versions of Python this gives a RuntimeWarning so this is less likely to cause problems now. >>> import numpy
>>> x=0
>>> y=numpy.int32(2*10**9)
>>> y
2000000000
>>> x+=y
>>> x
2000000000
>>> x+=y
>>> x
4000000000
>>> x*x
-2446744073709551616
>>> y*y
__main__:1: RuntimeWarning: overflow encountered in int_scalars
-1651507200
I didn't think it was possible to get integer wraparound in Python. I guess it's because the "int32" from numpy "breaks" x, which subsequently no longer behaves like a python variable.