Python 如何使用基于numpy ndarray的索引覆盖getitem方法?

Python 如何使用基于numpy ndarray的索引覆盖getitem方法?,python,numpy-ndarray,Python,Numpy Ndarray,我正在尝试基于numpy.ndarray构建一个类,该类\uuu getitem\uuuuuu和\uuuuuu setitem\uuuuuuu方法提供基于如下索引的数据点类: import numpy as np class Point: def __init__(self, number=20): dt = np.dtype([("x",np.float64), ("y",np.float64), ("alive",np.bool)]) self.po

我正在尝试基于numpy.ndarray构建一个类,该类
\uuu getitem\uuuuuu
\uuuuuu setitem\uuuuuuu
方法提供基于如下索引的数据
类:

import numpy as np

class Point:
    def __init__(self, number=20):
        dt = np.dtype([("x",np.float64), ("y",np.float64), ("alive",np.bool)])
        self.points = np.zeros((int(number),1), dtype=dt)
        self.points["alive"] = True

#    def __getitem__(self, i):
#        mask = self.points["alive"] == True
#        print("get")
#        return self.points[mask].__getitem__(i)

    def __getitem__(self, i):
        mask = self.points["alive"] == True
        print("get")
        return self.points[mask][i]

    def __setitem__(self, i, item):
        mask = self.points["alive"] == True
        print("set")
        self.points[mask][i] = item
如果我尝试:

p = Point()
print(p[0])
>>>>get
>>>>(0., 0., True)
print(p[0]["alive"])
>>>>get
>>>>True
p[0]["alive"] = False
>>>>get
print(p.points[0]["alive"])
>>>>[ True]
所以修改没有被考虑在内,但我没有得到任何错误,就像我在修改一个副本一样。此外,我还感到困惑,因为我调用的不是
\uuuuu setitem\uuuuu
方法,而是
\uuuu getitem\uuuuu
方法。我使用
ndarray
\uuu getitem\uuuuu
尝试了另一个实现,但存在相同的问题


我做错了什么,以及如何正确地做到这一点?

我找到了如何使用pandas来做到这一点,它允许在不使用链接索引的情况下实现这一点,并获得数组视图而不是副本:

import numpy as np
import pandas as pd

class Point:
    def __init__(self, number=20):
        d = {"x":np.zeros((int(number),)), "y":np.zeros((int(number),))}
        self.points = pd.DataFrame(d)
        self.alive = pd.Series(np.ones((int(number),),dtype=bool))

    def __getitem__(self, i):
        return self.points.loc[self.alive,i]

    def __setitem__(self, i, item):
        self.points.loc[self.alive,i] = item
这将提供正确的行为:

p = Point(3)
print(p[:])

>>>>     x    y
>>>> 0  0.0  0.0
>>>> 1  0.0  0.0
>>>> 2  0.0  0.0

p.alive[0] = False
print(p[:])

>>>>     x    y
>>>> 1  0.0  0.0
>>>> 2  0.0  0.0

p["x"] = p["x"] + 5
print(p[:])

>>>>     x    y
>>>> 1  5.0  0.0
>>>> 2  5.0  0.0


我找到了如何使用pandas来实现这一点,pandas允许在不使用链接索引的情况下实现这一点,并获得阵列视图而不是副本:

import numpy as np
import pandas as pd

class Point:
    def __init__(self, number=20):
        d = {"x":np.zeros((int(number),)), "y":np.zeros((int(number),))}
        self.points = pd.DataFrame(d)
        self.alive = pd.Series(np.ones((int(number),),dtype=bool))

    def __getitem__(self, i):
        return self.points.loc[self.alive,i]

    def __setitem__(self, i, item):
        self.points.loc[self.alive,i] = item
这将提供正确的行为:

p = Point(3)
print(p[:])

>>>>     x    y
>>>> 0  0.0  0.0
>>>> 1  0.0  0.0
>>>> 2  0.0  0.0

p.alive[0] = False
print(p[:])

>>>>     x    y
>>>> 1  0.0  0.0
>>>> 2  0.0  0.0

p["x"] = p["x"] + 5
print(p[:])

>>>>     x    y
>>>> 1  5.0  0.0
>>>> 2  5.0  0.0


我想做的有两个问题。首先,numpy数组高级索引(如points[mask])返回数组的一个副本,而不是一个视图,因此您无法将其指定给它。第二个是我使用了链式索引(比如[mask][I]),这意味着我调用类的getitem而不是numpy ndarray的getitem。更精确的是,我想做的有两个问题。首先,numpy数组高级索引(如points[mask])返回数组的一个副本,而不是一个视图,因此您无法将其指定给它。第二个是我使用了链式索引(比如[mask][I]),这意味着我调用类的getitem而不是numpy ndarray的getitem。这里更精确