我有一个来自库 (numpy.ndarray) 的对象,其中我用 _ iadd _ 方法替换了自定义方法。如果我调用 object._ iadd _(x),它会按预期工作。但是, object+=x 似乎调用了旧的(未替代的)方法。我想防止 numpy 在特定情况下发生溢出,所以我为此创建了一个上下文管理器。这是(仍然非常粗糙的)代码:
class NumpyOverflowPreventer( object ):
inverse_operator= {'__iadd__':'__sub__', '__isub__':'__add__', '__imul__': '__div__', '__idiv__':'__mul__'}
def _operate(self, b, forward_operator):
assert type(b) in (int, float)
reverse_operator= NumpyOverflowPreventer.inverse_operator[forward_operator]
uro= getattr(self.upper_range, reverse_operator)
lro= getattr(self.lower_range, reverse_operator)
afo= self.originals[ forward_operator ]
overflows= self.matrix > uro( b )
underflows= self.matrix < lro( b )
afo( b )
self.matrix[overflows]= self.upper_range
self.matrix[underflows]= self.lower_range
def __init__(self, matrix):
m= matrix
assert m.dtype==np.uint8
self.matrix= m
self.lower_range= float(0)
self.upper_range= float(2**8-1)
def __enter__(self):
import functools
self.originals={}
for op in NumpyOverflowPreventer.inverse_operator.keys():
self.originals[ op ] = getattr( self.matrix, op )
setattr( self.matrix, op, functools.partial(self._operate, forward_operator=op))
def __exit__(self, type, value, tb):
for op in NumpyOverflowPreventer.inverse_operator.keys():
setattr( self.matrix, op, self.originals[ op ] )
运行这个:
a= np.matrix(255, dtype= np.uint8)
b= np.matrix(255, dtype= np.uint8)
with NumpyOverflowPreventer(a):
a+=1
with NumpyOverflowPreventer(b):
b.__iadd__(1)
print a,b
返回这个:
[[0]] [[255]]