有没有一种方法可以输入提示Python装饰器,其参数必须是装饰函数参数的子类型?

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

我正在尝试实现一个Python重试装饰器,我可以在其中传递一个

return_value_generator
,如果函数用完重试尝试,它将生成一个返回值。

我目前有以下内容:

Param = ParamSpec('Param')
ReturnType = TypeVar('ReturnType')

def retry(*, retries: int = 3, return_value_generator: Callable[[], ReturnType] | None = None):
    def decorator(func: Callable[Param, Awaitable[ReturnType]]) -> Callable[Param, Awaitable[ReturnType]]:
        @functools.wraps(func)
        async def wrapper(*args: Param.args, **kwargs: Param.kwargs) -> ReturnType:
            retries_left = retries
            while True:
                try:
                    return await func(*args, **kwargs)
                except Exception:
                    if retries_left <= 0:
                        if return_value_generator is not None:
                            return return_value_generator()
                        raise

        return wrapper
    return decorator


@retry(return_value_generator=lambda: [None])
async def get_cache_values(cache, keys: list[str]) -> list[bytes | None]:
    """
    Returns cache values for the given keys or None if the cache doesn't
    exist for a specific key.
    """
    ...

类型检查器(pyright)在装饰函数上给我以下错误消息:

Type parameter "_T_co@Awaitable" is covariant, but "list[bytes | None]" is not a subtype of "list[None]"

问题似乎是我以一种方式定义装饰器,其中

return_value_generator
是定义返回类型的,但我实际上希望内部装饰函数定义
return_value_generator
的返回类型。

我希望类型检查器验证

list[bytes | None]
是否是
list[None]
 的子类型,而不是检查 
list[None]
 是否是 
list[bytes | None]

的子类型

有没有办法以这种方式设置装饰器?

我尝试创建一个新的类型变量,如下所示:

ReturnTypeSubtype = TypeVar('ReturnTypeSubtype', bound=ReturnType)

def retry(*, retries: int = 3, return_value_generator: Callable[[], ReturnTypeSubtype] | None = None):
    ...

但是我从

ReturnTypeSubtype
声明的类型检查器收到以下错误消息:

Type variable "ReturnType" has no meaning in this context

python decorator type-hinting pylance pyright
© www.soinside.com 2019 - 2024. All rights reserved.