You need to enable JavaScript to run this app. Python如何为接收可调用对象及参数的数值积分函数添加类型标注
优惠活动
大模型
产品
解决方案
定价
更多

Python如何为接收可调用对象及参数的数值积分函数添加类型标注

解决方案

你提到的PEP 612引入的ParamSpec(参数规范变量)完全可以满足需求,配合Concatenate就能精准约束func和args的类型关系,比自定义Protocol兼容性更好,也能直接适配lambda表达式。

完整类型标注实现

Python 3.10 兼容版本:

from typing import Callable, Concatenate, ParamSpec

P = ParamSpec("P")

def simple_quad(
    func: Callable[Concatenate[float, P], float],
    a: float,
    b: float,
    args: P.args = ()
) -> float:
    # 原有实现逻辑
    def strips(n: int):
        for i in range(n):
            x = a + (b - a) * i / n
            yield func(x, *args) * 1 / n

    return sum(strips(1000))

如果是Python 3.11及以上版本,可以用更简洁的*P写法,省略Concatenate:

from typing import Callable, ParamSpec

P = ParamSpec("P")

def simple_quad(
    func: Callable[[float, *P], float],
    a: float,
    b: float,
    args: tuple[*P] = ()
) -> float:
    # 原有实现逻辑

约束逻辑说明

  • Concatenate[float, P]明确要求func的第一个位置参数必须是float类型,返回值固定为float,剩余位置参数的长度、类型全部由P自动捕获
  • args的类型直接绑定P.args,也就是func除第一个参数外剩余位置参数对应的元组类型,mypy会自动校验传入的args元组是否和func的参数要求完全匹配
  • 对于存在必填仅限关键字参数(*后无默认值的参数)的函数,会因为不符合Callable的签名要求,直接被mypy拦截,完全符合禁止这类函数传入的需求

校验效果

你的所有测试用例都可以被mypy正确校验:

  • 传入cubic搭配args=(1,2,3,4):int是float的子类,类型兼容,无报错
  • 传入cubic但不带args:P捕获到需要4个float参数,空元组不匹配,mypy直接报错
  • 传入cubic搭配字符串类型的args:元组类型不匹配,mypy报错
  • 传入无额外参数的x_squared:P被推断为空参数,空元组匹配,无报错
  • 传入带必填仅限关键字参数的problematic:签名不匹配,mypy直接报错

该方案不需要自定义Protocol,天然兼容lambda、普通函数、绑定方法等所有可调用对象,非常适合用来写scipy的.pyi存根文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 12:45:06