2010-08-12 210 views
3

Python傳播者會說Python沒有switch語句的原因是因爲它有字典。那麼......我怎麼用字典來解決這個問題呢? 問題是,所有值正在評估一些並引發異常取決於輸入。Python懶惰字典評估

這只是一個存儲一個數字或一列數字並提供乘法的類的簡單例子。 「拉姆達:」我能解決這個問題。將前綴每個值

class MyClass(object): 

    def __init__(self, value): 
     self._value = value 

    def __mul__(self, other): 
     return { 
      (False, False): self._value * other._value      , 
      (False, True): [self._value * o for o in other._value]   , 
      (True , False): [v * other._value for v in self._value]   , 
      (True , True): [v * o for v, o in zip(self._value, other._value)], 
     }[(isinstance(self._value, (tuple, list)), isinstance(other._value, (tuple, list)))] 

    def __str__(self): 
     return repr(self._value) 
    __repr__ = __str__ 



>>> x = MyClass(2.0) 
>>> y = MyClass([3.0, 4.0, 5.0]) 
>>> print x 
2.0 
>>> print y 
[3.0, 4.0, 5.0] 
>>> print x * y 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 8, in __mul__ 
TypeError: can't multiply sequence by non-int of type 'float' 

一種方法字典查找後和調用lambda函數......「}(isinsta ...)」

有沒有更好的方法?

+1

採用*任何類型的值*的方法都是關於從OOP的角度來看最糟糕的事情,這就是爲什麼代碼看起來非常難看。 – 2010-08-12 21:05:02

回答

1

我能想到的在這裏兩種方法:

  • 一些if語句。對於TrueFalse這四種組合,情況並不糟糕。 if ...... elif ...... elif ......從我看到的這些子句中,在Python代碼中並不罕見。

  • 創建一次dict(作爲類字段,而不是實例字段),並在其中存儲(lambda)函數。這比前面的方法縮放得更好,對許多選項來說速度更快(儘管我不知道「很多」的價值)。

1

我認爲這裏的重點是可讀性。
作爲您展示的字典查找語言肯定難以閱讀,因此難以維護。

在我看來,編寫軟件的主要目標應該是可讀性;出於這個原因,我會去找一組if/elif直接比較這兩個值(而不是具有這些類型的映射)。那麼如果測量結果顯示性能問題,則可以探索其他解決方案(如帶有函數的字典查找)。

3

是,定義小lambda表達式爲這些不同的選擇:

def __mul__(self, other): 
     scalar_times_scalar = lambda x,y: x*y 
     scalar_times_seq = lambda x,y: [x*y_i for y_i in y] 
     seq_times_scalar = lambda x,y: scalar_times_seq(y,x) 
     seq_times_seq  = lambda x,y: [x_i*y_i for x_i,y_i in zip(x,y)] 
     self_is_seq, other_is_seq = (isinstance(ob._value,(tuple, list)) 
                for ob in (self, other)) 
     fn = { 
      (False, False): scalar_times_scalar, 
      (False, True): scalar_times_seq, 
      (True , False): seq_times_scalar, 
      (True , True): seq_times_seq, 
      }[(self_is_seq, other_is_seq)] 
     return fn(self._value, other._value) 

理想的情況下,當然,你只有一次在類或模塊範圍定義這些lambda表達式。我剛剛在__mul__方法中顯示了它們以方便參考。