加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python-如何对具有可选参数的装饰器进行类型注释?

发布时间:2020-12-17 17:39:17 所属栏目:Python 来源:网络整理
导读:这是我要正确键入注释的确切函数: F = TypeVar('F',bound=Callable[...,Any])def throtle(_func: Optional[F] = None,*,rate: float = 1) - Union[F,Callable[[F],F]]: """Throtles a function call,so that at minimum it can be called every `rate` seco

这是我要正确键入注释的确切函数:

F = TypeVar('F',bound=Callable[...,Any])

def throtle(_func: Optional[F] = None,*,rate: float = 1) -> Union[F,Callable[[F],F]]:
    """Throtles a function call,so that at minimum it can be called every `rate` seconds.

    Usage::

        # this will enforce the default minimum time of 1 second between function calls
        @throtle
        def ...

    or::

        # this will enforce a custom minimum time of 2.5 seconds between function calls
        @throtle(rate=2.5)
        def ...

    This will raise an error,because `rate=` needs to be specified::

        @throtle(5)
        def ...
    """

    def decorator(func: F) -> F:
        @functools.wraps(func)
        def wrapper(*args: Any,**kwargs: Any) -> Any:
            time.sleep(rate)
            return func(*args,**kwargs)

        return cast(F,wrapper)

    if _func is None:
        return decorator
    else:
        return decorator(_func)

尽管通过mypy进行插入时没有出现任何错误,但我不确信自己做对了,也不确定如何证明这一点.

最佳答案
您的代码会进行类型检查,但可能不会执行您想要的操作,因为您将返回一个Union.

要检查mypy推断某个变量的类型,可以使用reveal_type.

# Note: I am assuming you meant "throttle" and so I changed your spelling
def throttle1(
    _func: Optional[F] = None,rate: float = 1.0
) -> Union[F,F]]:
    # code omitted


@throttle1
def hello1() -> int:
    return 42


reveal_type(hello1) # Revealed type is 'Union[def () -> builtins.int,def (def () -> builtins.int) -> def () -> builtins.int]'

假设我们希望hello1是一个返回int的函数(即def()-> builtins.int),我们需要尝试其他方法.

简单策略

最简单的事情是始终要求节流阀的用户“呼叫装饰器”,即使她/他没有重写任何参数也是如此:

def throttle2(*,rate: float = 1.0) -> Callable[[F],F]:
    def decorator(func: F) -> F:
        @functools.wraps(func)
        def wrapper(*args: Any,wrapper)

    return decorator


@throttle2() # Note that I am calling throttle2 without arguments
def hello2() -> int:
    return 42

reveal_type(hello2) # Revealed type is 'def () -> builtins.int'


@throttle2(rate=2.0)
def hello3() -> int:
    return 42

reveal_type(hello3) # Revealed type is 'def () -> builtins.int'

这已经有效并且非常简单.

使用type.overload

如果先前的解决方案不可接受,则可以使用重载.

# Matches when we are overriding some arguments
@overload
def throttle3(_func: None = None,F]:
    ...

# Matches when we are not overriding any argument
@overload
def throttle3(_func: F) -> F:
    ...


def throttle3(
    _func: Optional[F] = None,F]]:
    # your original code goes here


@throttle3 # Note: we do not need to call the decorator
def hello4() -> int:
    return 42


reveal_type(hello4) # Revealed type is 'def () -> builtins.int'


@throttle3(rate=2.0)
def hello5() -> int:
    return 42


reveal_type(hello5) # Revealed type is 'def () -> builtins.int'

您可以通过阅读its official documentation和mypy’s documentation on Function overloading了解更多有关如何使用重载的信息.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读