函數重載是指定義多個具有相同名稱但不同簽名的函數的能力,這意味著它們具有不同數量或類型的參數。編譯器或解釋器會根據函數呼叫期間傳遞的參數數量和類型自動選擇函數的正確版本。
Java 和 C++ 等語言本身就支援此功能。
雖然 Python 本身不支援函數重載,因為它是一種動態類型語言,但可以使用各種模組和實用程式來實現相同的功能。
這是我的重載實作。
from __future__ import annotations import inspect import typing bin: dict[str, OverloadNamespace] = {} class OverloadNamespace: overloads: dict[tuple[type, ...], typing.Callable[..., typing.Any]] fallback: typing.Callable[..., typing.Any] def __init__(self, name: str) -> None: self.overloads = {} self.fallback = self._fallback bin[name] = self def __call__(self, *args: typing.Any, **kwds: typing.Any) -> typing.Any: types = [type(arg) for arg in args] types.extend([type(kwrg) for kwrg in kwds]) try: return self.overloads[tuple(types)](*args, **kwds) except KeyError: return self.fallback(*args, **kwds) @staticmethod def _fallback(*_, **__) -> None: raise NotImplementedError
OverloadNamespace 類別是一個可呼叫類,可作為函數名稱和呼叫簽名之間的媒介。參數被傳遞到 __call__ dunder 方法中,該方法將提供的資料類型與儲存在重載字典中的類型元組進行匹配。傳回符合的簽名,並使用提供的 args/kwargs 進行呼叫。如果沒有找到匹配的簽名,則呼叫後備函數。
此類不適合手動使用,它由裝飾器使用,修飾器修改函數並使用與函數提供的名稱相同的名稱傳回 OverloadNamespace 類別的實例。
def overload(*args) -> typing.Callable[..., OverloadNamespace] | OverloadNamespace: """Decorator used to create overloads of functions with same name. Returns a [OverloadNamespace]""" if len(args) == 1 and inspect.isfunction(args[0]): return overload_using_types(args[0]) def inner(func: typing.Callable[..., typing.Any]) -> OverloadNamespace: sig = inspect.signature(func) assert len(args) == len( sig.parameters ), "Number of types and args in function is not same." namespace = ( bin[func.__name__] if bin.get(func.__name__) else OverloadNamespace(func.__name__) ) namespace.overloads[tuple(args)] = func return namespace return inner def overload_using_types(func: typing.Callable[..., typing.Any]) -> OverloadNamespace: args = inspect.signature(func).parameters types = tuple(arg.annotation for arg in args.values()) namespace = ( bin[func.__name__] if bin.get(func.__name__) else OverloadNamespace(func.__name__) ) namespace.overloads[types] = func return namespace
重載裝飾器使用裝飾器值或類型提示檢查參數類型並傳回命名空間類別。
使用範例
# types in decorator @overload(int, int) def sum(a, b): return a+b # or as typehints @overload def sum(a: float, b: float): return int(a+b)+1 sum(1,2) # 3 sum(1.23, 2.0) # 4
這只是一個基本想法,適用於非聯合固定類型。
後備函數用作當沒有參數模式與呼叫模式匹配時要呼叫的函數。
def fallback( func: typing.Callable[..., typing.Any], ) -> OverloadNamespace: """Fallback function to be called if no overloads match to the provided arguments.""" namespace = ( bin[func.__name__] if bin.get(func.__name__) else OverloadNamespace(func.__name__) ) namespace.fallback = func return namespace @fallback def sum(*args): return sum(args) sum(1,2,3,4) # 10
以上是Python 中的重載函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!