微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

装饰器更改通用返回类型时的键入功能

如何解决装饰器更改通用返回类型时的键入功能

这与 Typing function when decorator change return type 类似,但这次具有通用返回类型

from typing import Generic,TypeVar,Generic,Callable,Any,cast

T = TypeVar('T')

class Container(Generic[T]):
    def __init__(self,item: T):
        self.item: T = item

def my_decorator(f: Callable[...,T]) -> Callable[...,Container[T]]:

    def wrapper(*args: Any,**kwargs: Any) -> Container[T]:
        return Container(f(*args,**kwargs))

    return cast(Callable[...,Container[T]],wrapper)

@my_decorator
def my_func(i: int,s: str) -> bool: ...

reveal_type(my_func) # Revealed type is 'def (*Any,**Any) -> file.Container[builtins.bool*]

要保持 my_func参数类型完整,需要哪种 mypy 法术?

使用 typing.Protocol 看起来很有希望,但我不知道如何让它发挥作用。

解决方法

使用 Callable[...,T] 是目前最好的注释方式。

PEP 612 引入了 ParamSpec,它的用法类似于 TypeVar,可以解决您的问题。它目前计划用于 Python 3.10,并将支持使用 typing_extensions

的旧版本

你会写:

T = TypeVar('T')
P = ParamSpec('P')

def my_decorator(f: Callable[P,T]) -> Callable[P,Container[T]]:

    def wrapper(*args: Any,**kwargs: Any) -> Container[T]:
        return Container(f(*args,**kwargs))

    return cast(Callable[P,Container[T]],wrapper)

mypy 对 PEP 612 的支持尚未完成:https://github.com/python/mypy/issues/8645。与 pytype(Google 的 python 类型检查器)相同。

pyright(微软的 python typechecker)和 pyre(facebook 的 python typechecker)已经支持 PEP 612

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。