2017-03-08 19 views
6

說我已經建立了包含Foo類庫,支持一些神奇的方法,說__add__()__radd__()python中是否有可擴展的魔術方法的最佳實踐?

>>> class Foo(object): 
...  def __add__(self, rhs): 
...   print("Foo.__add__", rhs) 
...  def __radd__(self, lhs): 
...   print("Foo.__radd__", lhs) 
... 
>>> foo = Foo() 
>>> foo + 3 
Foo.__add__ 3 
>>> 3 + foo 
Foo.__radd__ 3 

當計算3 + foo,蟒蛇首先調用type(3).__add__(3, foo),但截至返回NotImplemented,它回落到type(foo).__radd__(foo, 3)

>>> type(3).__add__(3, foo) 
NotImplemented 

我希望開發者能夠建立在我的庫頂庫,說含有類庫,我希望他們有完全的控制權。特別是,我想實施一些機制,讓其他圖書館可以決定foo + bar是否應撥打foo.__add__(bar)bar.__radd__(foo)

我看到NumPy使用__array_priority__方案解決了這個問題。但是這似乎引起了一些頭痛(考慮到有關這個問題的問題和問題的數量)。還有其他的最佳做法嗎?

+1

你是否也希望使用現有的類? –

+0

雖然你的問題很有意思,但缺乏細節。你能否描述期望行爲的更多方面? –

回答

1

一種流行的選擇是維持由LHS支持的類型的列表,如果RHS的類型是不在列表中,然後返回NotImplemented

class Foo(object): 
    SUPPORTED_TYPES = (int, Foo) 
    def __add__(self, rhs): 
     if isinstance(type(rhs), SUPPORTED_TYPES): 
      [...] # compute self + rhs 
     else: 
      return NotImplemented 

這種運作良好,除非rhs是一個聰明的亞型SUPPORTED_TYPES之一:它沒有辦法控制。此外,這種上市類型不是很靈活。依靠鴨子打字而不是硬編碼類型列表可能會更好。

1

一個簡單的選擇就是儘量讓LHS做任何需要做的(在下面的例子中,它調用RHS的value()方法),並在情況下,它拋出一個異常,抓住它,並返回NotImplemented

class Foo(object): 
    [...] 
    def __add__(self, rhs): 
     try: 
      return self._value + rhs.value() 
     except AttributeError: 
      return NotImplemented 

儘可能簡單,不需要維護SUPPORTED_TYPES的列表。但是,RHS實施與此任務無關的value()方法存在風險,因此可能有點風險。而且,rhs沒有簡單的方法來完全控制結果。

在Python中,它通常是更好地乞求原諒,而不是請求許可,如上面,但你可能更願意檢查rhsvalue()方法:

class Foo(object): 
    def __add__(self, rhs): 
     rhs_value_func = getattr(rhs, "value", None) 
     if rhs_value_func is None: 
      return NotImplemented 
     else: 
      return self._value + rhs_value_func() 
0

另一個選擇是使用這樣的屬性爲__foo_priority__,有點像NumPy的確實與其__array_priority__

class Foo(object): 
    __foo_priority__ = 0 
    def __add__(self, rhs): 
     delegate = True 
     try: 
      rhs_prio = type(rhs).__foo_priority__ 
      delegate = (self.__foo_priority__ < rhs_prio) 
     except AttributeError: 
      delegate = True 
     if delegate: 
      return NotImplemented 
     else: 
      return self.value_ + rhs.value() 

此選項稍微複雜一些,但非常靈活。此選項唯一的(次要)問題是它需要rhs的類型具有額外的屬性,因此如果它是不具有此屬性的現有類型,則無法對rhs進行控制。

相關問題