Python自定义自引用函数装饰器如何让VS Code正确显示对外参数
该方法可以让代码提示正确显示`arg_1`和`arg_2`参数,但每个自引用函数都需要额外编写重载声明,需要重复定义两次函数,不够Pythonic,算不上优雅的解决方案。我也尝试过给`custom_self`装饰器本身添加装饰处理,但没有得到预期效果。代码功能运行正常,仅编辑器参数提示不符合预期,请问有没有更优雅的实现方案? --- # 解决方案 你可以通过Python的`ParamSpec`类型注解实现需求,仅需要修改装饰器本身的类型标注,不需要为每个被装饰的函数额外写重载声明,完全符合Pythonic的要求。 具体实现代码如下: ```python from typing import Callable, ParamSpec, TypeVar from functools import wraps # 定义参数和返回值的泛型 P = ParamSpec("P") R = TypeVar("R") def custom_self(func: Callable[[Callable[P, R], *P.args], R]) -> Callable[P, R]: @wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> R: return func(func, *args, **kwargs) return wrapped
实现说明
ParamSpec是Python 3.10版本引入的类型变量,专门用于捕获函数的完整参数签名,完美保留原函数的参数提示、类型检查效果。如果你使用的是Python 3.10以下版本,可以安装typing-extensions包后从typing_extensions导入ParamSpec使用。- 装饰器入参
func的类型标注明确了原函数第一个参数是自身的函数引用,后续参数和返回值和最终暴露给用户的签名完全一致。 - 装饰器返回值的类型标注为
Callable[P, R],直接告诉编辑器和类型检查器,被装饰后的函数签名就是原函数去掉第一个own参数后的签名,自动隐藏不需要用户传入的参数。 - 搭配
functools.wraps可以保留原函数的函数名、文档字符串等所有元信息。
使用示例
@custom_self def new_func(own, arg_1: int, arg_2: str) -> None: """测试自引用函数""" own.arg_1 = arg_1 own.arg_2 = arg_2 # 此时编辑器悬停new_func时,提示会自动显示为 new_func(arg_1: int, arg_2: str) -> None new_func(1, "测试")
该方案已经适配VS Code的Pylance插件、mypy等主流类型检查工具,不需要对业务代码做任何额外修改。
内容的提问来源于stack exchange,提问作者Mr_HxID
相关产品推荐
相关产品推荐

