Numpy arrays can be efficiently subclassed, but I want to modify the behavior of __getitem__
and __setitem__
so they can take in a datetime range, while preserving the maximum amount of built-in machinery like operations, cumsum, etc. Can this be done with __array_ufunc__
?
It appears that in their example, the numpy.ufunc.at
method is overridden.
Could this be used to modify the get/set behavior of numpy arrays?
You can implement __getitem__
and __setitem__
to handle your specific cases (with datetime objects) and dispatch to super().__{get|set}item__
in other cases. That way the remaining functionality of ndarray
remains preserved. For example:
from datetime import date
import numpy as np
class A(np.ndarray):
def __array_finalize__(self, obj):
if obj is not None:
obj.start_date = date.today()
def __getitem__(self, item):
if isinstance(item, slice) and isinstance(item.start, date) and isinstance(item.stop, date):
return super().__getitem__(slice((item.start - self.start_date).days,
(item.stop - self.start_date).days,
item.step))
return super().__getitem__(item)
a = A((10,), buffer=np.arange(10), dtype=int)
print(a[1:8])
print(a[date(2019, 1, 22):date(2019, 1, 29):2])
print(np.cumsum(a))
print(np.add.outer(a, a))
Which outputs:
[1 2 3 4 5 6 7]
[1 3 5 7]
[ 0 1 3 6 10 15 21 28 36 45]
[[ 0 1 2 3 4 5 6 7 8 9]
[ 1 2 3 4 5 6 7 8 9 10]
[ 2 3 4 5 6 7 8 9 10 11]
[ 3 4 5 6 7 8 9 10 11 12]
[ 4 5 6 7 8 9 10 11 12 13]
[ 5 6 7 8 9 10 11 12 13 14]
[ 6 7 8 9 10 11 12 13 14 15]
[ 7 8 9 10 11 12 13 14 15 16]
[ 8 9 10 11 12 13 14 15 16 17]
[ 9 10 11 12 13 14 15 16 17 18]]