模式匹配是如何提高可讀性的——一個面向小白的例子

這只是實際工程中遇到的一個簡單的例子。

該代碼出現的位置在github.com/thautwarm/In

我們把題意抽取出來,看看這個問題。

對於一個輸入的dict, 我們輸出一個dict,並且使得對於鍵值s, m, l,它們的值分別為12:4:3。

要求如下:

1. 輸入的dict中, 若對於鍵值s, m, l 均為整數,則返回該dict。

2. 輸入的dict中,只有s, m, l中的一個鍵且對應值為整數,自動根據 12:4:3的比例得出其他鍵的值,並返回補充後的dict。

3. 其餘情況, 報錯。其中當沒有以上三種里任何一種鍵出現時,做特殊提醒。

其實呢,這個題倒不一定用模式匹配,但我在這裡說,有三個原因:

  1. 安利flowpython(展示可讀性。
  2. 關於模式匹配的擴展。
  3. 展示一種根據直觀思路快速解決問題的方法。

代碼如下(此處的self是一個字典)

s = None if "s" not in self else self["s"]n m = None if "m" not in self else self["m"]n l = None if "l" not in self else self["l"]n condic[] (s,m,l):nn case (None, None, None) =>n raise ValueError("Number of input arguments cannot be zero!!! ")nn case (Rule(.x->x.__class__ is int), None, None) =>n self["m"] = self["s"]//2n self["l"] = self["s"]//3nn case (None, Rule(.x->x.__class__ is int), None) =>n self["s"] = self["m"]*2n self["l"] = self["s"]//3nn case (None, None, Rule(.x->x.__class__ is int)) =>n self["s"] = self["l"]*3n self["m"] = self["s"]//2nn (.x -> map(type, x) -> tuple(_))n case (int,int,int) =>n passnn otherwise =>n raise ValueError("Do not support initializing <class grid> with these arguments!!!")n

就是首先製造一個要測試的值,此處即是元組(s, m, l)。

根據題意,當s,m,l皆未定義時,做特殊報錯,這就是第一個case。

(None, None, None) == (s, m, l)n

時, 進行該case下的動作。

然後看第二個case,出現了一個Rule。

看一下Rule的定義。

class Rule:n def __init__(self, f):n self.f = fn def __eq__(self, v):n if self.f(v):n return Truen else:n return Falsen

也就是說傳入一個函數f來初始化Rule類得到一個instance,當這個instance和任何值比較時,如果返回真值True,也即f(instance)為真,此處即判斷元組中某個值是否為整數類型。

這作為原生python對flowpython模式匹配的一個擴展,類似的還有Any等等。

回到主題,後面三個case是類似的,看最後一個case,這裡使用了一個特殊匹配模式。condic關鍵字默認的模式是 [==], 用以比較case匹配量和condic測試值的相等關係,若想等則進行該case的動作。

但我們還可以定義更多的模式,例如(function),根據括弧里的一個函數,我們把它用到condic測試值上,如果與case匹配量相等,則進行該case的動作。

在代碼的最後一個case里,即是求出(s, m, l)三者的類型,並以元組形式返回,並與case匹配量(int, int, int)比較, 即判斷

(s.__class__, m.__class__, l.__class__) == (int, int, int)n

是否成立,若成立直接返回字典self。

最後,是其他情況,在otherwise處直接報錯。

當然,這顯然不是最智慧的辦法,但我認為它非常好懂。如果你理解了上面的模式匹配,你可以試著將case的數量減少為2個。以及你可能會使用到flowpython模式匹配里的捕獲方法,我建議你閱讀 Wiki thautwarm/flowpython。


推薦閱讀:

誤刪除pycharm項目中的文件,如何恢復?
數據可視化工具matplotlib複習總結
python是對面向對象編程友好的語言嗎?有沒有改進空間?
Python 網路爬蟲入門(四)— 破解pexels高清原圖 (附源碼)
Python · 樸素貝葉斯(三)· GaussianNB

TAG:Python | 设计模式 |