2012-02-25 140 views
2

我想要一類函數中定義一個類的實例運營商,像這樣:重載運營商

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) 

然而,這似乎並沒有工作 - 我覺得我失去了一些東西約運營商-+等如何調用這些功能。即:

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 

在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 
+1

對於運營商首要的先進(涼爽)示例,請參閱[這裏]( http://stackoverflow.com/a/7844038/566644)對我在SO上提出的問題進行了精彩的回答。 – 2012-02-25 19:02:02

回答

6

特殊的方法,如__add__()正在擡頭的對象類型,而不是實例。所以

a + b 

大致翻譯成

type(a).__add__(a, b) 

這意味着在實例設置__add__沒有做什麼有用的(除了使a.__add__(b)工作)。

你的例子有點不完整,所以我不能提供完整的工作代碼。您可以將代碼從_define_arithmetic_attributes()移至課程正文,並從operation_wrapper()內部訪問self.threshold

(請注意,我沒有得到_arithmetic_threshold屬性點。你爲什麼不乾脆訪問self.threshold本身?)

+0

關於「財產」的好問題 - 我更新了示例以說明我的意圖。有沒有更好的方式來做我正在做的事情?即根據閾值重新設置'__add__'方法?我真正想要做的只是在兩個實例之間進行算術運算,只要它們的某些屬性(光譜的X軸...)在某個閾值內達成一致,否則會回想一下例外情況 – keflavich 2012-02-25 18:19:01

+0

,您對訪問的評論''operation_wrapper'內的'self.threshold'可能是一種可行的方法。 – keflavich 2012-02-25 18:21:51

+0

@keflavich:爲了給你更多的信息,我需要知道'_operation_wrapper()'的樣子。也許有一種完全不同的方法。 – 2012-02-25 19:40:53