简体   繁体   English

在函数中覆盖运算符

[英]Overriding operators within functions

I want to define operators for a class instance within a class function, like so: 我想在类函数中为类实例定义运算符,如下所示:

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)

However, this doesn't seem to work - I feel like I'm missing something about how the operators - , + , etc, call these functions. 但是,这似乎不起作用-我感觉好像缺少关于运算符-+等如何调用这些函数的内容。 ie: 即:

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

in MyClass2, the behavior of __add__ will be different. 在MyClass2,行为__add__会有所不同。 Can anyone explain how they are different, and how to make the behavior of the operator methods in MyClass similar to MyClass2? 谁能解释它们的不同之处,以及如何使MyClass中的操作符方法的行为类似于MyClass2?

EDIT: Just to make clear why I'm trying to do this, here's _operation_wrapper . 编辑:只是为了弄清楚为什么我要这样做,这是_operation_wrapper The class this is a method of is a "Spectrum" object, which has an X-axis and a Y-axis. 这是一个方法类,是“光谱”对象,具有X轴和Y轴。 The goal is to allow arithmetic on the Y axes, but only if the X axes match. 目的是允许在Y轴上进行算术运算,但前提是X轴匹配。 However, it is acceptable for them to match to, say, 1/5th of a pixel size, so I wanted to do more that pure 'exact' matching. 但是,它们可以匹配到像素大小的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

Special methods like __add__() are looked up on the type of the object, not on the instance. __add__()这样的特殊方法是在对象的类型上查找的,而不是在实例上查找的。 So 所以

a + b

is roughly translated to 大致翻译成

type(a).__add__(a, b)

This means that setting __add__ on the instance does not do anything useful (except for making a.__add__(b) work). 这意味着在实例上设置__add__不会做任何有用的事情(除了使a.__add__(b)起作用)。

Your example is a bit incomplete, so I can't provide full working code. 您的示例有点不完整,因此我无法提供完整的工作代码。 You might be able to move the code from _define_arithmetic_attributes() to the class body and access self.threshold from inside operation_wrapper() . 您可能可以将代码从_define_arithmetic_attributes()移到类主体,并可以从operation_wrapper()内部访问self.threshold

(Note that I don't get the point of the _arithmetic_threshold property. Why don't you simply access self.threshold itself?) (请注意,我_arithmetic_threshold属性的_arithmetic_threshold 。为什么不简单地访问self.threshold本身?)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM