I want to subclass np.ndarray in order to create a class for 2D points with most of the Numpy machinery still available and some additional methods specific to 2D arrays. One of those methods is rotating the point around the origin. I tried that by using matrix multiplication and then assigning the data attribute of the result to my point.
>>> import numpy as np
>>> class Point2D(np.ndarray):
... def __new__(cls, coords):
... point = np.array(coords, dtype=float).view(cls)
... if point.shape != (2,):
... raise ValueError("A Point2D needs exactly two coordinates.")
... return point
...
... def rotate(self, angle):
... self.data = (np.array([[np.cos(angle), -np.sin(angle)],
... [np.sin(angle), np.cos(angle)]]) @ self).data
...
>>> x = Point2D((1, 0))
>>> x.rotate(np.pi/2)
__main__:10: DeprecationWarning: Assigning the 'data' attribute is an inherently unsafe operation and will be removed in the future.
The deprecation warning urges me not to assign the data attribute. What should I do instead?
dataattribute of a Numpy array provides amemoryview()of the same array. It allows raw byte-level access to the array data. You want high-level access to your elements, therefore the answer of Eric works fine. Also, as amemoryviewinstance is an object with methods to allow access to the data and corresponding metadata rather than the raw data itself, assigning to.datawould (in general) replace the memoryview with something completely different rather than just writing to the data and thus isn't desirable in any conceivable practical case, hence the warning..datadoes not replace the memoryview with something else, as Numpy package code does "magic" when performing the assignment. But it will still affect other things than just the raw data and the array may behave unexpectedly henceforth. It's also not a good way of accessing.data. Not that it matters for your particular case. Just clarifying my previous comment.