如何为类实现的装饰编写类型提示

问题描述 投票:0回答:1

这是一个由类实现的装饰器的经典示例:

class Decorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        self.func(*args, **kwargs)

如何使

__call__
具有与
func
相同的签名和类型提示?

我尝试过以下代码:

from typing import Callable, TypeVar, ParamSpec, Generic

PT = ParamSpec('PT')
RT = TypeVar('RT')


class Decorator(Generic[PT, RT]):
    def __init__(self, func: Callable[PT, RT]) -> None:
        self.func = func

    def __call__(self, *args: PT.args, **kwargs: PT.kwargs) -> RT:
        return self.func(*args, **kwargs)


@Decorator
def add(x: int, y: int) -> int:
    return x + y

但我未能在 PyCharm 中获得

add
的正确参数列表。

是 PyCharm 的错吗?

PyCharm screenshot

python pycharm python-decorators python-typing
1个回答
0
投票

您希望将函数显式替换为具有特定签名的可调用函数,而不是使用工作原理相同但不共享签名的可调用类替换该函数。

具体方法如下:

from typing import Callable, TypeVar, ParamSpec, Generic

PT = ParamSpec('PT')
RT = TypeVar('RT')


class Decorator(Generic[PT, RT]):
    def __init__(self, func: Callable[PT, RT]) -> None:
        self.func = func

    def __call__(self, *args: PT.args, **kwargs: PT.kwargs) -> RT:
        return self.func(*args, **kwargs)


def decorator(func: Callable[PT, RT]) -> Callable[PT, RT]:
    return Decorator(func)


@decorator
def add(x: int, y: int) -> int:
    return x + y


print(add(1, 2))

您会发现类型提示和类型检查现在都可以正常工作,在 PyCharm 中也是如此。虽然,当您使用该类作为装饰器时,类型检查可以工作,但类型提示会如您在问题中所示那样显示。

© www.soinside.com 2019 - 2024. All rights reserved.