2017-07-24 31 views
0

我有兩個類FooBar抑制__add__時__radd__定義

class Foo(str): 
    def __add__(self, other): 
     return 'Foo.__add__ called' 


class Bar(str): 
    def __radd__(self, other): 
     return 'Bar.__radd__ called' 

正如你所看到的,我已經Foo實施__add__Bar實施__radd__

我可以創建這些類的對象並添加它們,因爲定義了魔術方法。

f = Foo('foo') 
b = Bar('bar') 

然而,增加他們產生這樣的:

In [390]: f + b 
Out[390]: 'Foo.__add__ called' 

如何設置它,這樣Bar.__radd__方法被調用優先於Foo.__add__?從docs有關__rstuff__方法

+0

製作'Bar' Foo'的'子類。 –

+0

@AshwiniChaudhary嘿,你知道什麼。這工作。好一個。把它變成答案? :)(關於如何工作會有所幫助的小解釋...) –

回答

1

有兩種方法可以做到這一點。

  1. Foo中添加明確的支票與Bar相關。

class Foo(str): 
    def __add__(self, other): 
     if isinstance(other, Bar): 
      return NotImplemented 
     return 'Foo.__add__ called' 


class Bar(str): 
    def __radd__(self, other): 
     return 'Bar.__radd__ called' 
  • BarFoo一個子類。
  • From docs:

    注:如果右操作數的類型是左操作數的 類的子類,該子類提供了 操作反射的方法,這個方法會被之前被叫左操作數的 不反映的方法。這種行爲允許子類覆蓋其祖先的操作 。

    2

    報價:

    這些功能僅稱爲如果左操作數不支持相應的操作和操作數是不同的類型。例如,爲了評估表達式x - y,其中y是具有__rsub__()方法的類的實例,如果x.__sub__(y)返回NotImplemented,則調用y.__rsub__(x)

    所以,你的情況,Foo,左操作數,確實有__add__方法,因此,它立即調用。爲避免這種情況,如果其他參數的類型爲Bar,則可以從Foo.__add__中獲得return NotImplemented

    1

    正如Datamodel部分Python的參考文檔中說明,通過Python的順序使用,以解決這種情況下:在第一個操作數

    1. 支票__add__
    2. 且僅當沒有執行檢查第二個是__radd__

    解決您的問題(不是真的很漂亮/ Python的),一種可能性是在你的__add__實施檢查other實現__radd__方法。

    例如有:

    class Foo(str): 
        def __add__(self, other): 
         try: 
          return other.__radd__(self) 
         except NotImplemented: 
          pass 
         # __radd__ not implement so return __add__ behavior 
         return 'Foo.__add__ called' 
    

    有了結果:

    In [5]: f + b 
    Out[5]: 'Bar.__radd__ called'