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

如何为带可调用参数及默认值的函数正确添加类型提示?

问题:为带默认可调用参数的函数添加正确的类型提示

我尝试给一个接收可调用参数(默认值为set)的函数添加类型提示,写了如下代码:

from typing import Callable, List
T = TypeVar("T")
def transform(data: List[int], ret_type: Callable[[List[int]], T] = set) -> T:
    return ret_type(data)

a = [1, 2, 3]
my_set: Set = transform(a)

这段代码触发了mypy的错误提示:

mypy3: Incompatible default for argument "ret_type" (default has type "Type[Set[Any]]", argument has type "Callable[[List[int]], T]")

请问ret_type的正确类型应该是什么?

编辑补充
以下代码虽不够理想但可正常运行(参考@chepner的评论):

from typing import cast, Any, Callable, TypeVar

T = TypeVar("T")

def transform(data: Any, ret_type: Callable[..., T] = cast(Callable, set)) -> T:
    return ret_type(data)

正确的类型标注方案

问题核心在于:set是类型构造器(类型为Type[Set[Any]]),而非直接符合Callable[[List[int]], T]的可调用对象。下面是几种可行的修正方案:

方案1:针对集合类型的精确标注

如果ret_type只需要支持集合类的构造器,可以用Type明确标注,并通过bound约束TypeVar的范围:

from typing import List, Type, Set, TypeVar

T = TypeVar("T", bound=Set[int])
def transform(data: List[int], ret_type: Type[T] = set) -> T:
    return ret_type(data)

a = [1, 2, 3]
my_set: Set[int] = transform(a)

方案2:兼容多种可调用对象

如果希望ret_type既支持类型构造器,也支持普通函数,可以用Union组合Type和Callable类型:

from typing import Callable, List, Type, Set, TypeVar, Union

T = TypeVar("T")
def transform(data: List[int], ret_type: Union[Type[T], Callable[[List[int]], T]] = set) -> T:
    return ret_type(data)

a = [1, 2, 3]
my_set: Set[int] = transform(a)
# 也能传入自定义函数
def to_list(lst: List[int]) -> List[int]:
    return lst.copy()
my_list: List[int] = transform(a, to_list)

方案3:用Protocol实现严格类型约束(Python 3.8+)

如果需要更精确的类型检查,可定义一个Protocol来统一匹配所有能接收List[int]的可调用对象(包括类型构造器):

from typing import List, TypeVar, Protocol, Set

T = TypeVar("T")

class AcceptsListInt(Protocol[T]):
    def __call__(self, lst: List[int]) -> T: ...

def transform(data: List[int], ret_type: AcceptsListInt[T] = set) -> T:
    return ret_type(data)

a = [1, 2, 3]
my_set: Set[int] = transform(a)

原代码报错原因

mypy会严格区分“类型本身”和“普通可调用对象”:set作为默认值,它的类型是Type[Set[Any]],表示这是一个用来创建Set[Any]的类型;而你标注的Callable[[List[int]], T]指的是一个直接接收List[int]并返回T的函数/可调用对象,两者类型不匹配,因此触发错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:24:27