前段時間學習C++,發現C++有個函式多載的情況,
(以下介紹來自百度百科)多載函式是函式的一種特殊情況,為方便使用,C++允許在同一范圍中宣告幾個功能類似的同名函式,但是這些同名函式的形式引數(指引數的個數、型別或者順序)必須不同,也就是說用同一個函式完成不同的功能,這就是多載函式,多載函式常用來實作功能類似而所處理的資料型別不同的問題,不能只有函式回傳值型別不同,
我查了一下關于Python的函式多載,發現Python并不支持函式多載,
但是,我發現可以通過其他的一些方法,來實作這個函式多載,
通過在網上搜索,找到一些使用Python實作函式多載的方法,這其中就有幾種“假的”函式多載,他們根本就沒有領會到函式多載的優雅之處,
最后看到一個博客上寫的用Python實作的函式多載,我覺得非常的好,在這里就與大家分享一下,
博客來源:https://arpitbhayani.me/blogs/function-overloading
實作程序主要分為三個部分,1、包裝函式(Wrapped the function);2、構建虛擬命名空間(Building the virtual Namespace);3、使用使用裝飾器作為鉤子(Using decorators as a hook),
/01/ 包裝函式
包裝函式的目的在于,可以包裝任何函式,并通過一個被覆寫的__call__方法使其可呼叫,同時它還公開了一個名為key的方法,該方法會回傳一個元組,這使得這個函式在整個代碼庫中是唯一的,
class Function(object): def __init__(self, fn): self.fn = fn def __call__(self, *args, **kwargs): fn = Namespace.get_instance().get(self.fn, *args) if not fn: raise Exception("No matching function found.") return fn(*args, *kwargs) def key(self, args=None): if args is None: args = getfullargspec(self.fn).args return tuple( [ self.fn.__module__, self.fn.__class__, self.fn.__name__, len(args or []), ] )
/02/ 構建虛擬命名空間
構建的虛擬命名空間將存盤我們在定義階段收集的所有函式,由于這里只有一個命名空間/注冊表,我們創建了一個單例類來將函式保存在一個字典中,這個字典的鍵將不僅僅是一個函式名,而是我們從key函式獲得的元組,它包含了在整個代碼庫中唯一標識函式的元素,通過這樣做,我們就可以在注冊表中保存函式了,即使它們有相同的名稱(但有不同的引數),從而促進函式多載,
class Namespace(object): __instance = None def __init__(self): if self.__instance is None: self.function_map = dict() Namespace.__instance = self else: raise Exception("Cannot instantiate a virtual Namespace again") @staticmethod def get_instance(): if Namespace.__instance is None: Namespace() return Namespace.__instance def register(self, fn): func = Function(fn) self.function_map[func.key()] = fn return func def get(self, fn, *args): func = Function(fn) return self.function_map.get(func.key(args=args))
/03/ 使用裝飾器作為鉤子
因此,創建了名為overload的裝飾器,它會在虛擬命名空間中注冊這個新包裝器函式并回傳一個可呼叫物件,
def overload(fn): return Namespace.get_instance().register(fn)
/04/ 測驗
@overload def area(a, b): s = a * b print("長方形的面積是:", s) return s @overload def area(r): s = 3.14 * r ** 2 print("圓的面積是:", round(s, 2)) return s @overload def area(a, b, c) -> float: v = a * b * c print("立方體的體積是:", v) return v if __name__ == "__main__": area(2) area(3, 4) area(1, 2, 3)
這才是有靈魂的函式多載嘛!
▼?
函式多載也算是為自己多提供了一個思路,
?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/184534.html
標籤:Python
