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

如何实现支持多装饰构建参数类型Union且单装饰校验正常的装饰器?

解决方案:使用TypeVarTuple + Unpack实现兼容单/多装饰的类型安全注册器

核心思路是利用Python 3.10+的TypeVarTuple和Unpack特性,收集多次装饰传入的所有Event类型,将处理器函数的参数约束为这些类型的联合类型,同时保证单装饰场景下的严格校验。

实现代码

from typing import TypeVar, Callable, ParamSpec, TypeVarTuple, Unpack, Union

# 基础Event类和类型变量
E = TypeVar('E', bound='Event')
class Event:
    pass

class A(Event):
    pass

class B(Event):
    pass

# 定义用于收集多装饰Event类型的TypeVarTuple
Events = TypeVarTuple('Events')
P = ParamSpec('P')

def register(event_type: type[Unpack[Events]]) -> Callable[[Callable[[Union[Unpack[Events]], ...], None]], Callable[[Union[Unpack[Events]], ...], None]]:
    def decorator(func: Callable[[Union[Unpack[Events]], ...], None]) -> Callable[[Union[Unpack[Events]], ...], None]:
        # 这里添加实际的注册逻辑(比如将函数绑定到事件类型)
        return func
    return decorator

场景测试

1. 单装饰场景(严格类型校验)

# ✅ 合法:参数类型与装饰器指定的A一致
@register(A)
def handle_a(event: A) -> None:
    pass

# ❌ 类型错误:参数是B,但装饰器要求A
@register(A)
def handle_b(event: B) -> None:
    pass

2. 多装饰场景(支持Union参数)

# ✅ 合法:参数是A|B,匹配两次装饰的类型
@register(A)
@register(B)
def handle_either(event: A | B) -> None:
    pass

# ✅ 合法:参数是A(属于A|B的子集)
@register(A)
@register(B)
def handle_a_only(event: A) -> None:
    pass

# ❌ 类型错误:参数是未注册的C类型
class C(Event):
    pass

@register(A)
@register(B)
def handle_c(event: C) -> None:
    pass

方案优势

  • 单装饰时,Union[Unpack[Events]]等价于单个Event类型,保持严格的参数校验,不会出现register3的错误提示问题。
  • 多装饰时,自动将所有注册的Event类型合并为Union,完美适配参数为联合类型的处理器函数,解决register1的误报问题。
  • 相比ParamSpec实现的register2,通过明确约束参数为注册类型的联合,能准确触发预期的类型错误。

可选:严格约束参数必须是全量Union

如果需要强制处理器函数的参数必须是所有注册类型的完整联合(不允许子集),可以调整装饰器的类型签名:

def register(event_type: type[Unpack[Events]]) -> Callable[[Callable[[Union[Unpack[Events]]], None]], Callable[[Union[Unpack[Events]]], None]]:
    def decorator(func: Callable[[Union[Unpack[Events]]], None]) -> Callable[[Union[Unpack[Events]]], None]:
        return func
    return decorator

此时handle_a_only会触发类型错误,因为参数是A而非A|B。

内容的提问来源于stack exchange,提问作者MaPePeR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:56:21