需要存储一个bool numpy数组,但它必须与旧规范(astropy.io.fits.ImageHDU)兼容,该规范只能存储int8(其他类型也是可能的,但int8是最小的内存占用)。关键问题是,用户想要做的是,
mask = np.array((True, False, False, True))
print(np.arange(4, 8)[mask])
[4, 7]
如果掩码为int,则给予完全不同的结果
[5, 4, 4, 5]
这里有两个(错误的)实现,可以给予我所需要的概念
import numpy as np
class MyClass(dict):
@property
def mask(self):
return self['mask'].astype(bool)
@mask.setter
def mask(self, inmask):
self['mask'] = inmask.astype(np.int8)
input_mask = np.array((0, 1), dtype=np.int8)
obj = MyClass((('mask', input_mask),))
所需的行为应该使obj.mask
和obj['mask']
始终同步,即
print(obj.mask)
[False, True]
print(obj['mask'])
[0, 1]
obj['mask'][0] = 1
print(obj.mask)
[True, True]
obj.mask[0] = False
print(obj.mask)
[False, True]
print(obj['mask'])
[0, 1]
但是实现失败了,因为mask
总是返回与self['mask']
不同的示例。所以,作为替代,我试着
import numpy as np
class MyClass(dict):
@property
def mask(self):
try:
return self._mask
except AttributeError:
self._mask = self['mask'].astype(bool)
return self._mask
@mask.setter
def mask(self, inmask):
self._mask = inmask
self['mask'] = inmask.astype(np.int8)
input_mask = np.array((0, 1), dtype=np.int8)
obj = MyClass((('mask', input_mask),))
此操作失败,因为self._mask
和self['mask']
不同步
obj.mask[0] = True
print(obj.mask, ' - ', obj['maks'])
[True True] - [0 1]
1条答案
按热度按时间rn0zuynd1#
在这个特定的设置中,我会直接利用Numpy中布尔数组的值是用字节处理的这一事实(即,8位值)。我不完全确定这是否被认为是一个实现细节,但到目前为止,它对我很有效。
这意味着我们可以使用Numpy的
ndarray.view()
来创建掩码内存的两个表示:布尔表示(用于实际屏蔽)和int8表示(用于规范一致性)。由于这两种表示都引用同一个内存,这意味着它们已经保持同步,不需要我们做进一步的工作。调整你第一次尝试的实现,我们可以这样写:
这将给我们给予预期的行为:
注意,在这个实现中,我们实际上有 * 三个 * 相同内存的表示:进入setter的
inmask
,obj['mask']
和obj.mask
。如果我们想确保在改变obj.mask
或obj['mask']
时inmask
不会改变(或者,同样地,对inmask
的改变不会改变obj.mask
和obj['mask']
),我们可以像以前一样在setter中使用astype()
。