覆盖函数内的运算符

kef*_*ich 2 python overriding

我想在类函数中为类实例定义运算符,如下所示:

class MyClass(object):

    @property
    def _arithmetic_threshold(self):
        return self.threshold # this will be defined somewhere

    @_arithmetic_threshold.setter
    def _arithmetic_threshold(self,value):
        self.threshold = value
        self._define_arithmetic_attributes()

    def _define_arithmetic_attributes(self):
        """
        Wrapper to define all arithmetic attributes (in order to allow threshold changes)
        """

        self.__add__ = self._operation_wrapper(np.add,threshold=self._arithmetic_threshold)
        self.__sub__ = self._operation_wrapper(np.subtract,threshold=self._arithmetic_threshold)
        self.__mul__ = self._operation_wrapper(np.multiply,threshold=self._arithmetic_threshold)
        self.__div__ = self._operation_wrapper(np.divide,threshold=self._arithmetic_threshold)
Run Code Online (Sandbox Code Playgroud)

然而,这似乎并没有工作-我觉得我失去了一些东西有关如何运营商-,+等,调用这些函数.即:

class MyClass2(object):
    def __add__(self,other,threshold=None):
        if threshold is not None:
            return self+other
        else:
            # do something here involving checking a threshold....
            pass
Run Code Online (Sandbox Code Playgroud)

在MyClass2中,行为__add__会有所不同.任何人都可以解释它们是如何不同的,以及如何使MyClass中的运算符方法的行为类似于MyClass2?

编辑:只是为了弄清楚我为什么要这样做,这里是_operation_wrapper.这是一种方法,是一种"光谱"对象,它有一个X轴和一个Y轴.目标是允许Y轴上的算术运算,但仅限于X轴匹配.但是,它们可以匹配,例如,像素大小的1/5,所以我想做更多纯粹的"精确"匹配.

def _operation_wrapper(operation):
    """
    Perform an operation (addition, subtraction, mutiplication, division, etc.)
    after checking for shape matching
    """

    def ofunc(self, other): 
        if np.isscalar(other):
            newspec = self.copy()
            newspec.data = operation(newspec.data, other) 
            return newspec
        else: # purely for readability

            if self._arithmetic_threshold == 'exact':
                xarrcheck = all(self.xarr == other.xarr)
            else:
                if self._arithmetic_threshold_units is None:
                    # not sure this should ever be allowed
                    xarrcheck = all((self.xarr-other.xarr) < self._arithmetic_threshold)
                else:
                    xarrcheck = all((self.xarr.as_unit(self._arithmetic_threshold_units)-other.xarr.as_unit(self._arithmetic_threshold_units)) < self._arithmetic_threshold)

            if self.shape == other.shape and xarrcheck:
                newspec = self.copy()
                newspec.data = operation(newspec.data, other.data)
                return newspec
            elif self.shape != other.shape:
                raise ValueError("Shape mismatch in data")
            elif not xarrcheck:
                raise ValueError("X-axes do not match.")

    return ofunc
Run Code Online (Sandbox Code Playgroud)

Sve*_*ach 6

__add__()查找对象类型的特殊方法,而不是实例.所以

a + b
Run Code Online (Sandbox Code Playgroud)

大致翻译为

type(a).__add__(a, b)
Run Code Online (Sandbox Code Playgroud)

这意味着__add__实例的设置没有任何用处(除了a.__add__(b)工作).

您的示例有点不完整,因此我无法提供完整的工作代码.您可以将代码从_define_arithmetic_attributes()类主体移动到self.threshold内部并从内部访问operation_wrapper().

(请注意,我没有得到_arithmetic_threshold财产的要点.为什么不简单地访问self.threshold自己?)