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