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

如何为Python中Foo类的fn1、fn2和kwargs添加正确类型注解?

如何为Python中Foo类的参数添加类型注解以约束kwargs同时满足多个函数要求

问题描述

我想给下面代码里Foo类的fn1、fn2和**kwargs添加类型注解:

class Foo:
    def __init__(self, fn1, fn2, **kwargs):
        self.res1 = fn1(**kwargs)
        self.res2 = fn2(**kwargs)

需要让kwargs同时满足fn1和fn2的输入参数要求,避免出现这种错误场景:

# 因kwargs缺少key y,fn2执行失败
Foo(fn1=lambda x: x+1, fn2=lambda x,y:x+y, x=1)

想问在Python 3.11或3.12版本中,能不能实现正确的类型注解?

之前处理单参数情况时,我用typing.TypeVar实现的代码如下:

from typing import Callable, TypeVar

T = TypeVar('T')


class Foo:
    def __init__(self, fn1: Callable[[T], T], fn2: Callable[[T], T], x: T):
        self.res1 = fn1(x)
        self.res2 = fn2(x)


# mypy类型检查失败
Foo(lambda x, y: x+1, lambda y: y*2, x=5)

# mypy类型检查通过
Foo(lambda x: x+x, lambda y: y*2, x='a')
Foo(lambda x: x+x, lambda y: y*2, x=3.14)

运行mypy file.py的输出:

file.py:13: error: Cannot infer type of lambda  [misc]
file.py:13: error: Argument 1 to "Foo" has incompatible type "Callable[[Any, Any], Any]"; expected "Callable[[int], int]"  [arg-type]
Found 2 errors in 1 file (checked 1 source file)

解决方案

在Python 3.11/3.12中,可以通过**typing.ParamSpec和TypeVar结合**来实现这种对kwargs的约束,确保传入的关键字参数同时满足fn1和fn2的参数要求。

具体实现代码

from typing import Callable, ParamSpec, TypeVar

P = ParamSpec('P')
R1 = TypeVar('R1')
R2 = TypeVar('R2')

class Foo:
    def __init__(
        self,
        fn1: Callable[P, R1],
        fn2: Callable[P, R2],
        **kwargs: P.kwargs,
    ):
        self.res1 = fn1(**kwargs)
        self.res2 = fn2(**kwargs)

类型检查效果验证

测试错误场景:

# mypy会报错:缺少参数y
Foo(fn1=lambda x: x+1, fn2=lambda x,y:x+y, x=1)

测试合法场景:

# 检查通过,kwargs同时满足两个函数的参数要求
Foo(fn1=lambda x: x+1, fn2=lambda x,y:x+y, x=1, y=2)
# 检查通过,两个函数仅需x参数
Foo(fn1=lambda x: x+1, fn2=lambda x:x*2, x=3)

原理说明

  • ParamSpec('P')用于捕获函数的参数签名(包括位置参数和关键字参数)
  • Callable[P, R1]表示fn1的参数签名必须匹配P,返回值类型为R1;fn2同理
  • **kwargs: P.kwargs明确要求传入的kwargs必须完全匹配P所捕获的关键字参数集合,这样就能保证kwargs同时满足fn1和fn2的参数要求

注意:这个特性需要使用支持ParamSpec的类型检查器,比如mypy 0.910+或者pyright,Python 3.10及以上版本原生支持ParamSpec(从typing模块导入)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:28:10