Getters and setters seem to behave weirdly when performing += with numpy arrays due to in-place mutation: a += b behaves differently from a = b + a when b is a numpy array.
A minimal example is the following class (note that the setter does not modify _x in order to show that the act of setting _x is not needed to achieve this behavior):
class Foo:
    def __init__(self,x_val):
        self._x = x_val
    
    @property
    def x(self):
        return self._x
    
    @x.setter
    def x(self, new_x):
        print(f'old_x = {self._x}; new_x = {new_x}')
The following works correctly, where the instance variable is an integer:
a = Foo(2)
print(a.x)  # Prints: 2
a.x = a.x + 2  # Prints: old_x = 2; new_x = 4
print(a.x)  # Prints: 2
a.x += 2  # Prints: old_x = 2; new_x = 4
print(a.x)  # Prints: 2
But when the instance variable is a numpy array, += differs from + (!)
import numpy as np
b = Foo(np.array([1, 2]))
print(b.x)  # Prints: [1 2]
b.x = np.array([1, 2]) + b.x  # Prints: old_x = [1 2]; new_x = [2 4]
print(b.x)  # Prints: [1 2]
b.x += np.array([1, 2])  # Prints: old_x = [2 4]; new_x = [2 4]
print(b.x)  # Prints: [2 4]
It looks as though += is modifying the b._x array object it got in place, after addition, too! This seems like a strange default for numpy's __iadd__() function to have. How do I get b.x += y to work like b.x = y + b.x? Must @property's always output copies of objects that implement __iadd__() to prevent this from happening? Is it a bug in numpy?
Python version: 3.7.13
Numpy version: 1.21.5