如何为将int转换为str的Python装饰器添加正确类型提示?
为参数转换装饰器添加类型提示
要让mypy正确识别装饰器将int参数转为str的行为,需要结合Python的类型提示工具(如ParamSpec、TypeVar、TypeVarTuple等)来精确标注装饰器的输入输出类型。以下是两种可行的实现方案:
方案1:针对任意参数数量的通用实现(Python 3.11+)
使用TypeVarTuple和Unpack处理任意数量的参数,将每个原参数类型扩展为原类型 | int,确保mypy能识别调用时传入int是合法的:
from typing import Callable, TypeVarTuple, Unpack, TypeVar, Union, Any # 定义类型变量:捕获原函数的参数类型元组和返回值类型 Args = TypeVarTuple("Args") R = TypeVar("R") def convert_int_to_str( func: Callable[[Unpack[Args]], R] ) -> Callable[[Unpack[tuple[Union[Arg, int] for Arg in Args]]], R]: def wrapper( *args: Unpack[tuple[Union[Arg, int] for Arg in Args]], **kwargs: Any ) -> R: # 将位置参数中的int转为str converted_args = tuple(str(arg) if isinstance(arg, int) else arg for arg in args) # 将关键字参数中的int转为str converted_kwargs = { key: str(value) if isinstance(value, int) else value for key, value in kwargs.items() } return func(*converted_args, **converted_kwargs) return wrapper
使用示例
@convert_int_to_str def foo(x: str) -> str: return f"foo{x}" # mypy不会报错,因为装饰后的函数接受int或str print(foo(4)) # 输出 'foo4' @convert_int_to_str def bar(a: str, b: str) -> str: return f"{a}{b}" bar(1, "2") # 输出 '12',mypy识别合法
方案2:针对固定参数数量的重载实现(兼容旧Python版本)
如果使用Python 3.10及以下版本,无法使用TypeVarTuple,可以通过@overload为不同参数数量的函数分别标注类型:
from typing import Callable, TypeVar, overload R = TypeVar("R") StrOrInt = TypeVar("StrOrInt", str, int) # 重载:单参数函数 @overload def convert_int_to_str(func: Callable[[str], R]) -> Callable[[StrOrInt], R]: ... # 重载:双参数函数 @overload def convert_int_to_str(func: Callable[[str, str], R]) -> Callable[[StrOrInt, StrOrInt], R]: ... # 通用实现 def convert_int_to_str(func: Callable[..., R]) -> Callable[..., R]: def wrapper(*args, **kwargs) -> R: converted_args = tuple(str(arg) if isinstance(arg, int) else arg for arg in args) converted_kwargs = {k: str(v) if isinstance(v, int) else v for k, v in kwargs.items()} return func(*converted_args, **converted_kwargs) return wrapper
关键说明
- 两种方案的核心都是告诉mypy:装饰后的函数允许接受int类型参数,这些参数会被自动转为str,符合原函数的参数要求。
- 方案1更灵活,支持任意数量的参数,但需要Python 3.11+;方案2通过重载兼容旧版本,但需要手动添加对应参数数量的重载标注。
内容的提问来源于stack exchange,提问作者ignoring_gravity
相关产品推荐
相关产品推荐

