You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现支持带参Callable与无参Callable的通用装饰器并通过类型检查?

如何实现支持带参Callable与无参Callable的通用装饰器并通过类型检查?

我完全懂你的需求——想搞一个全能的装饰器deco3,既能适配和被装饰函数签名完全匹配的带参回调,也能兼容无参的回调函数,同时还要让PyRight这类类型检查器不报错。你现在的代码运行没问题,但类型检查通不过,核心原因是类型检查器没办法自动区分fn的两种不同Callable类型,得给它明确的“分支提示”才行。

解决这个问题的最佳方案是使用函数重载(@overload),通过定义不同的函数签名,让类型检查器根据传入的fn类型,匹配对应的处理逻辑。下面是具体的实现:

import inspect
from typing import Any, Callable, ParamSpec, TypeVar, overload

P = ParamSpec("P")
T = TypeVar("T")

# 重载1:处理无参的回调函数
@overload
def deco3(fn: Callable[[], Any]) -> Callable[[Callable[P, T]], Callable[P, T]]:
    ...

# 重载2:处理和被装饰函数签名一致的带参回调
@overload
def deco3(fn: Callable[P, Any]) -> Callable[[Callable[P, T]], Callable[P, T]]:
    ...

# 实际实现逻辑
def deco3(
    fn: Callable[[], Any] | Callable[P, Any],
) -> Callable[[Callable[P, T]], Callable[P, T]]:
    def decorator(wrapped_fn: Callable[P, T]) -> Callable[P, T]:
        def inner(*args: P.args, **kwargs: P.kwargs) -> T:
            # 运行时判断回调是否需要参数
            if len(inspect.signature(fn).parameters) > 0:
                # 类型检查器会根据重载推断fn是Callable[P, Any]
                fn(*args, **kwargs)
            else:
                # 类型检查器会推断fn是Callable[[], Any]
                fn()
            return wrapped_fn(*args, **kwargs)
        return inner
    return decorator

# 测试用的回调函数
def logger1(x: int, y: str) -> None:
    print(f"logger1: x={x}, y={y}")

def logger2() -> None:
    print(f"logger2")

# 测试装饰器
@deco3(logger1)
def wrapped_with_logger1(x: int, y: str) -> None:
    ...

@deco3(logger2)
def wrapped_with_logger2(x: int, y: str) -> None:
    ...

# 调用测试,类型检查器不会报错
wrapped_with_logger1(1, "test")  # 输出: logger1: x=1, y=test
wrapped_with_logger2(1, "test")  # 输出: logger2

为什么这个方案能解决问题?

  • 我们通过@overload给deco3定义了两个明确的签名:
    • 当传入的fn是无参函数时,装饰器可以接受任意签名的被装饰函数,因为无参回调不需要传递参数。
    • 当传入的fn是带参函数时,装饰器要求被装饰函数的签名和fn完全一致,这样类型检查器能确保参数传递是安全的。
  • 运行时的inspect.signature判断逻辑和原来一致,但类型检查器会根据重载的定义,在不同分支下自动推断fn的类型,从而消除报错。

这样既保留了你想要的通用功能,又能让类型检查器完全满意,完美兼顾运行时正确性和类型安全性~

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 11:14:36