Heim  >  Artikel  >  Backend-Entwicklung  >  Überladen von Funktionen in Python

Überladen von Funktionen in Python

DDD
DDDOriginal
2024-09-24 06:24:45650Durchsuche

Overloading functions in Python

Funktionsüberladung bezieht sich auf die Fähigkeit, mehrere Funktionen mit demselben Namen, aber unterschiedlichen Signaturen zu definieren, was bedeutet, dass sie unterschiedliche Anzahlen oder Typen von Parametern haben. Die richtige Version der Funktion wird automatisch vom Compiler oder Interpreter ausgewählt, abhängig von der Anzahl und Art der beim Funktionsaufruf übergebenen Argumente.

Sprachen wie Java und C++ unterstützen dies nativ als Funktion.

Während Python das Überladen von Funktionen nicht nativ unterstützt, da es sich um eine dynamisch typisierte Sprache handelt, ist es möglich, dasselbe mithilfe verschiedener Module und Dienstprogramme zu implementieren.

Dies ist meine Umsetzung von Überlastung.

Durchführung

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

Die OverloadNamespace-Klasse ist eine aufrufbare Klasse, die als Medium zwischen dem Funktionsnamen und der Aufrufsignatur fungiert. Die Argumente werden an die __call__-dunder-Methode übergeben, die die bereitgestellten Datentypen mit den im Überladungswörterbuch gespeicherten Typtupeln abgleicht. Die übereinstimmende Signatur wird zurückgegeben und mit den bereitgestellten Argumenten/Kwargs aufgerufen. Wird keine passende Signatur gefunden, wird die Fallback-Funktion aufgerufen.

Verwendung der OverloadNamespace-Klasse

Diese Klasse ist nicht für die manuelle Verwendung gedacht, sie wird von Dekorateuren verwendet, die die Funktion ändern und eine Instanz der OverloadNamespace-Klasse zurückgeben, die denselben Namen wie der von der Funktion bereitgestellte Name verwendet.

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

Der Überladungsdekorator überprüft die Argumenttypen mithilfe des Dekoratorwerts oder von Typhinweisen und gibt die Namespace-Klasse zurück.

Beispielverwendung

# 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

Dies ist nur eine Grundidee und funktioniert für nicht-gewerkschaftlich festgelegte Typen.

Zurückgreifen

Fallback-Funktionen werden als aufzurufende Funktion verwendet, wenn keine Argumentmuster mit dem Aufrufmuster übereinstimmen.

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

Das obige ist der detaillierte Inhalt vonÜberladen von Funktionen in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn