
@singledispatch
@singledispatch 允許函數充當 dispatch generic 函數 (single dispatch 函數),意味著它根據其第一個參數的類型具有不同的行為。 在其他編程語言中,此功能有時也稱為 "overloading"。
一旦定義了 single dispatch 函數,來自其他 libraries 或 modules 的程式碼,就可以用新的情況擴充它。 這意味著它們可以新增方法來處理您在編寫原始函數時未處理或不知道的類型。
如果您正在編寫 libraries,您的使用者可以輕鬆擴充該功能,以處理您未預料到的類型或用例。 同樣,如果您正在處理具有許多貢獻者的大型程式碼 libraries,則程式碼的不同部分可以向函數新增功能,而無需修改函數的原始定義。 這可以使程式碼更容易維護,並隨著時間的推移而發展。
如果您的類型檢查需求很簡單,並且不同類型的行為不太複雜,那麼使用 if 語句或單獨的函數可能是更簡單、更直接。
Overloading 有助於組織代碼,提高可讀性,並使得將來更容易將函數的功能擴展到其他類型。
@singledispatch 幫助您組織取決於特定類型參數的函數的不同實現,而不是擁有一個具有許多 if/elif 分支的單一函數,或者許多名稱略有不同的不同函數。
Python 本身並不支持 overloading,但 @singledispatch 是實現類似結果的 Pythonic 方法。要向函數新增 overloading 實現,請使用通用函數的 .register 屬性,該屬性可以用作 decorator。 對於用type annotations (PEP 484) 的函數,decorator 將自動推斷第一個參數的類型,您也可以顯式地將類型參數傳遞給 .register() 屬性。
.register 的簽名必須 base 函數的簽名符合。(即 @<function>.register)
為了能夠註冊 lambda 和預先存在的函數,.register 屬性也可以以函數形式使用。 .register 屬性返回未修飾的函數。
這使得 @<function>.register 能夠獨立地 stacking、 pickling、為每個 @<function>.register 建立 unit tests。
dispatch generic (single dispatch) 函數
dispatch generic (single dispatch) 函數是由多個方法組成的函數,即使它們以相同的方式調用,它也會根據單個參數的類型執行不同的操作。
這個概念也稱為函數 overloading,廣泛應用於許多物件導向的語言中。 Python 作為一種動態類型語言,不支持傳統意義上的函數 overloading。 但是,從 Python 3.4 開始,提供了 @singledispatch 來提供類似的功能。
範例 – Type annotations
_ 在 Python 中用作一次性變數的約定。(函數是匿名的)
這裡的 verbose 參數只是一個標誌,允許開發人員或使用者控制函數應輸出多少訊息,這對於 debugging 或理解函數正在做什麼非常有幫助。
在許多 programming contexts 中很常見。尤其是在不同 contexts 中,使用的函數或 scripts。
範例 – @.register
範例 – @.register 跨 module
@singledispatchmethod
它是 @singledispatch 的演變,設計用於實例方法 (Class 方法)。
@<method>.register 第一個參數是實例 (self) 或 Class (cls),第二個參數是考慮調度的參數。
@singledispatchmethod 支援與其他 decorators 嵌套。但 @singledispatchmethod, @<method>.register 必須是最外層 decorators。
例如:@classmethod, @staticmethod, @abstractmethod
reduce()
functools.reduce(function, iterable[,initializer]) 提供了一種以累積方式,將帶有兩個參數的函數 (binary function) 應用於 iterable 中的所有項目的方法。
如果提供了 initializer,它將用作減少過程中的初始值。 如果不是,則使用 iterable 的第一個元素。
減少過程:將函數應用於 iterable 的前兩個元素,然後再次將函數應用於結果和下一個元素,依此類推,直到處理完所有元素。
reduce() 有時會使程式碼更難以理解。 它通常可以替換為 built-in 函數或簡單迴圈,這可以使您的程式碼更易於閱讀和 debugging。
reduce() 始終返回單個資料,該值可以是任何數據類型。 返回的資料類型由您提供給 reduce() 的函數決定。
reduce() 大致等效以下程式碼 (詳見:itertools.accumulate()):
範例:
cmp_to_key()
functools.cmp_to_key(func) 主要是為了幫助將 Python 2 程式碼遷移到 Python 3 程式碼,Python 3 程式碼不支持 cmp 但支持 key。對於大多數 Python 3 任務,您可以放心地忽略它。
參考資料
你應該要知道的 Python 實用模組 - functools 教學 - MyApollo
functools — Higher-order functions and operations on callable objects — Python 3.11.4 documentation
Last updated