可以在没有参数的情况下使用的打字装饰器
我有一个可以在没有或有争论的情况下打电话给的装饰器(所有字符串):
@decorator
def fct0(a: int, b: int) -> int:
return a * b
@decorator("foo", "bar") # any number of arguments
def fct1(a: int, b: int) -> int:
return a * b
我很难提供适当的类型提示,因此,尽管阅读了 mypy of mypy 的相关部分。
这是我到目前为止尝试过的:
from typing import overload, TypeVar, Any, Callable
F = TypeVar("F", bound=Callable[..., Any])
@overload
def decorator(arg: F) -> F:
...
@overload
def decorator(*args: str) -> Callable[[F], F]:
...
def decorator(*args: Any) -> Any:
# python code adapted from https://stackoverflow.com/q/653368
# @decorator -> shorthand for @decorator()
if len(args) == 1 and callable(args[0]):
return decorator()(args[0])
# @decorator(...) -> real implementation
def wrapper(fct: F) -> F:
# real code using `args` and `fct` here redacted for clarity
return fct
return wrapper
这导致以下来自 mypy
的错误:
error: Overloaded function implementation does not accept all possible arguments of signature 1
我在 pyright
:上也有一个错误:
error: Overloaded implementation is not consistent with signature of overload 1
Type "(*args: Any) -> Any" cannot be assigned to type "(arg: F@decorator) -> F@decorator"
Keyword parameter "arg" is missing in source
我正在使用Python 3.10.4 ,mypy 0.960,Pyright 1.1.249。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题来自第一个过载(我应该读取
Pyright
消息两次!):此过载接受一个关键字参数,名为
arg arg
,而实现则没有!当然,对于
@decorator
符号使用的装饰器而言,这当然无关紧要,但是如果它被称为So:fct2 = Decorator(arg = fct)
> 。python> = 3.8
解决问题的最佳方法是更改第一个过载,以便
arg
a 仅位置参数(因此不能用作关键字参数):支持Python< 3.8
由于仅位置参数带有Python 3.8,因此我们无法根据需要更改第一个过载。
取而代之的是,让我们更改实现,以允许
** Kwargs
参数(另一种可能性是添加关键字arg
参数)。但是现在我们需要在代码实施中正确处理它,例如:The issue comes from the first overload (I should have read the
pyright
message twice!):This overload accepts a keyword parameter named
arg
, while the implementation does not!Of course this does not matter in the case of a decorator used with the
@decorator
notation, but could if it is called like so:fct2 = decorator(arg=fct)
.Python >= 3.8
The best way to solve the issue would be to change the first overload so that
arg
is a positional-only parameter (so cannot be used as a keyword argument):With support for Python < 3.8
Since positional-only parameters come with Python 3.8, we cannot change the first overload as desired.
Instead, let's change the implementation to allow for a
**kwargs
parameter (an other possibility would be to add a keywordarg
parameter). But now we need to handle it properly in the code implementation, for example: