如何基于部分TypedDict实现Python包装函数(适配mypy)
解决Python包装函数复用TypedDict时的参数重叠问题
要实现修改上游函数method1的参数a默认值、其余关键字参数原样传递,同时复用上游Method1Kwargs TypedDict避免维护成本,可通过以下两种方式解决mypy的参数重叠错误:
方案1:Python 3.12+ 原生支持(推荐)
Python 3.12和mypy 1.5以上版本新增了TypedDict的exclude参数,可直接继承上游TypedDict并排除指定键,生成仅包含剩余参数的新TypedDict,完全同步上游变更。
from typing import TypedDict # 上游库代码 class Method1Kwargs(TypedDict): a: int b: str c: float def method1(**kwargs: Method1Kwargs) -> None: print(f"a={kwargs['a']}, b={kwargs['b']}, c={kwargs['c']}") # 你的包装函数实现 # 继承Method1Kwargs并排除键'a' class Method2Kwargs(Method1Kwargs, exclude={"a"}): pass def method2(a: int = 10, **kwargs: Method2Kwargs) -> None: # 传递自定义默认值的a和其余参数给上游函数 method1(a=a, **kwargs)
此方案中,若上游Method1Kwargs新增或删除参数,Method2Kwargs会自动同步,无需手动修改代码,彻底解决维护成本问题。
方案2:兼容Python 3.11及以下版本
对于旧版本Python,可使用typing_extensions.NotRequired标记原TypedDict中的a为可选参数,同时在包装函数中显式定义a的默认值。虽然允许kwargs中传递a,但实际调用上游函数时会被包装函数的a参数覆盖,逻辑不受影响。
from typing import TypedDict from typing_extensions import NotRequired # 上游库代码 class Method1Kwargs(TypedDict): a: int b: str c: float def method1(**kwargs: Method1Kwargs) -> None: print(f"a={kwargs['a']}, b={kwargs['b']}, c={kwargs['c']}") # 你的包装函数实现 class Method2Kwargs(Method1Kwargs): # 将a标记为可选,避免与函数参数冲突 a: NotRequired[int] def method2(a: int = 10, **kwargs: Method2Kwargs) -> None: method1(a=a, **kwargs)
为什么之前的方案不可行?
- 手动定义不含
a的新TypedDict:每次上游函数签名变更都需要同步修改新TypedDict,维护成本高。 - 复制上游函数签名:同样需要跟随上游变更修改包装函数签名,无法自动同步。
内容的提问来源于stack exchange,提问作者Scott B
相关产品推荐
相关产品推荐

