>  기사  >  백엔드 개발  >  Python의 함수 오버로딩

Python의 함수 오버로딩

DDD
DDD원래의
2024-09-24 06:24:45499검색

Overloading functions in Python

함수 오버로드는 이름은 같지만 시그니처가 다른 여러 함수를 정의하는 기능을 의미합니다. 즉, 매개변수의 수나 유형이 다릅니다. 함수 호출 중에 전달된 인수의 수와 유형에 따라 컴파일러나 해석기가 자동으로 올바른 버전의 함수를 선택합니다.

Java 및 C++와 같은 언어는 기본적으로 이 기능을 지원합니다.

파이썬은 동적 유형 언어이기 때문에 기본적으로 함수 오버로딩을 지원하지 않지만, 다양한 모듈과 유틸리티를 사용하여 동일하게 구현하는 것은 가능합니다.

이것은 오버로딩을 구현한 것입니다.

구현

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를 사용하여 호출됩니다. 일치하는 서명이 없으면 fallback 함수가 호출됩니다.

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

이것은 단지 기본적인 아이디어이며 비조합 고정 유형에 적용됩니다.

대체

Fallback 함수는 호출 패턴과 일치하는 인수 패턴이 없을 때 호출되는 함수로 사용됩니다.

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으로 문의하세요.