包装另一个函数的函数的类型提示,接受相同的参数

Som*_*Guy 7 python type-hinting

def function(a: int, b: str) -> None:
    pass 

def wrapper(extra: int, *args, **kwargs) -> None:
    do_something_with_extra(extra)
    function(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

有没有一种简单的方法可以让包装器继承 function() 的类型提示而无需重新输入所有类型提示?通常我会写

def wrapper(extra: int, a: int, b: str) -> None:
Run Code Online (Sandbox Code Playgroud)

但由于有很多参数,它变得非常冗长,每次更新 function() 的参数时,我都必须更新wrapper(),并且 using*args, **kwargs意味着 vscode 和其他编辑器中不会有正确的自动完成功能。

小智 6

您能做的最好的事情就是使用装饰器来实现此目的,并且您可以使用ConcatenateParamSpec。我使用 python 3.8,我必须typing_extensions为它们安装。在下面的代码中,如果您在 VSCode 中键入 function,它将显示 int 参数,但前面没有“额外”名称。

from typing import Callable, TypeVar
from typing_extensions import Concatenate, ParamSpec


P = ParamSpec('P')
R = TypeVar('R')

def wrapper(func: Callable[P, R]) -> Callable[Concatenate[int, P], R]:
    def inner(extra, *args, **kwargs):
        print(extra)
        func(*args, **kwargs)
    
    return inner

@wrapper
def function(a: int, b: str) -> None:
    print(a, b)
    pass 

# typing function will show 'function: (int, a: int, b: str) -> None'
Run Code Online (Sandbox Code Playgroud)

  • 这不是我要问的,请注意我没有使用装饰器。我只是从包装器内部调用该函数。它也可能是一个闭包,因此装饰器将没有选择。 (4认同)