如何用Python泛型为Blinker Signal的kwargs提供类型提示?
解决方案:泛型绑定Sender与Kwargs类型的TypedSignal
要解决blinker Signal的参数类型检查冗余、签名不一致问题,可结合TypedDict、泛型Protocol与Generic实现一套可复用的类型安全信号封装,同时保证send和connect的签名完全绑定。
实现代码
from typing import Generic, TypeVar, TypedDict, Callable, Protocol from blinker import Signal # 定义Sender类型变量 T = TypeVar("T") # 约束Kwargs必须是TypedDict类型 K = TypeVar("K", bound=TypedDict) # 定义接收器的协议,统一约束sender和kwargs类型 class ReceiverProtocol(Generic[T, K], Protocol): def __call__(self, sender: T, **kwargs: K) -> None: ... # 泛型TypedSignal,继承自blinker.Signal class TypedSignal(Generic[T, K], Signal): def send(self, sender: T, **kwargs: K) -> list[tuple[Callable, None]]: return super().send(sender, **kwargs) def connect(self, receiver: ReceiverProtocol[T, K]) -> Callable: return super().connect(receiver)
使用示例
# 定义业务实体 class User: pass # 定义该信号要求的kwargs类型(必须为TypedDict) class UserUpdateKwargs(TypedDict): time: int audit: str # 实例化类型安全的信号 user_update = TypedSignal[User, UserUpdateKwargs]() # 正确的接收器:参数类型完全匹配 @user_update.connect def handle_user_update(sender: User, *, time: int, audit: str) -> None: print(f"User updated: {sender}, time: {time}, audit: {audit}") # 正确调用:sender和kwargs类型符合要求 user_update.send(User(), time=1620000000, audit="admin_operation") # 以下操作会触发mypy类型检查错误 # 错误:缺少audit参数 # user_update.send(User(), time=1620000000) # 错误:sender类型不匹配 # @user_update.connect # def bad_receiver(sender: str, time: int, audit: str) -> None: ...
方案优势
- 无冗余代码:每个信号仅需定义对应的
TypedDict即可,无需重复子类化Signal - 签名强绑定:
send和connect共享同一组泛型参数(T为sender类型,K为kwargs类型),避免两者签名不一致导致的运行时错误 - 完整类型检查:mypy会严格校验
send的kwargs参数、接收器的参数类型与定义的约束完全匹配
对原尝试问题的解释
- 仅支持位置参数的ParamSpec方案:未结合
TypedDict约束kwargs,无法满足blinker以kwargs传递后续参数的场景 - TypeVarTuple方案:mypy对
**Unpack[TypeVarTuple]的支持有限,仅允许TypedDict作为**参数的类型来源,因此直接使用TypeVarTuple无法实现kwargs的强类型检查 - ParamSpec+Protocol方案:错误地将Protocol直接作为泛型参数传入,正确的做法是定义泛型Protocol,让
TypedSignal绑定Protocol的类型参数,而非直接传入Protocol类型
类型系统支持性
当前Python类型系统(配合mypy 1.9.0)完全支持该需求,通过TypedDict+泛型Protocol的组合,可完美实现blinker信号的类型安全封装。
内容的提问来源于stack exchange,提问作者Michoel
相关产品推荐
相关产品推荐

