two - set difference python




Difference between a-= b and a=a-b in Python (2)

I have recently applied this solution for averaging every N rows of matrix. Although the solution works in general I had problems when applied to a 7x1 array. I have noticed that the problem is when using the -= operator. To make a small example:

import numpy as np

a = np.array([1,2,3])
b = np.copy(a)

a[1:] -= a[:-1]
b[1:] = b[1:] - b[:-1]

print a
print b

which outputs:

[1 1 2]
[1 1 1]

So, in the case of an array a -= b produces a different result than a = a - b . I thought until now that these two ways are exactly the same. What is the difference?

How come the method I am mentioning for summing every N rows in a matrix is working e.g. for a 7x4 matrix but not for a 7x1 array?


Internally, the difference is that this:

a[1:] -= a[:-1]

is equivalent to this:

a[1:] = a[1:].__isub__(a[:-1])
a.__setitem__(slice(1, None, None), a.__getitem__(slice(1, None, None)).__isub__(a.__getitem__(slice(1, None, None)))

while this:

b[1:] = b[1:] - b[:-1]

maps to this:

b[1:] = b[1:].__sub__(b[:-1])
b.__setitem__(slice(1, None, None), b.__getitem__(slice(1, None, None)).__sub__(b.__getitem__(slice(1, None, None)))

In some cases, __sub__() and __isub__() work in a similar way. But mutable objects should mutate and return themselves when using __isub__() , while they should return a new object with __sub__() .

Applying slice operations on numpy objects creates views on them, so using them directly accesses the memory of the "original" object.


The docs say :

The idea behind augmented assignment in Python is that it isn't just an easier way to write the common practice of storing the result of a binary operation in its left-hand operand, but also a way for the left-hand operand in question to know that it should operate `on itself', rather than creating a modified copy of itself.

As a thumb rule, augmented substraction ( x-=y ) is x.__isub__(y) , for IN -place operation IF possible, when normal substraction ( x = x-y ) is x=x.__sub__(y) . On non mutable objects like integers it's equivalent. But for mutable ones like arrays or lists, as in your example, they can be very different things.







in-place