首頁  >  文章  >  後端開發  >  Python 中的重載函數

Python 中的重載函數

DDD
DDD原創
2024-09-24 06:24:45670瀏覽

Overloading functions in Python

函數重載是指定義多個具有相同名稱但不同簽名的函數的能力,這意味著它們具有不同數量或類型的參數。編譯器或解釋器會根據函數呼叫期間傳遞的參數數量和類型自動選擇函數的正確版本。

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 類別

此類不適合手動使用,它由裝飾器使用,修飾器修改函數並使用與函數提供的名稱相同的名稱傳回 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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn