[英]Can I use a typing.Callable type to annotate a function automatically? How?
Suppose we define a type for a callback like so:假设我们像这样为回调定义一个类型:
CallbackFn = Callable[[str, str, int, int], None]
When I want to implement a callback function, and have external tools type-check it against CallbackFn
, I have to annotate the types explicitly:当我想实现回调 function 并让外部工具根据
CallbackFn
对其进行类型检查时,我必须显式注释类型:
def my_callback(s1: str, s2: str, i1: int, i2: int) -> None:
...
Is there any way that I can use the type hint defined in CallbackFn
to annoate a function - something like def my_callback(s1,s2,i1,i2) as CallbackFn:
- to avoid the explicit annotation work?有什么方法可以使用
CallbackFn
中定义的类型提示来注释 function - 类似于def my_callback(s1,s2,i1,i2) as CallbackFn:
- 以避免显式注释工作?
In a few cases, yes.在少数情况下,是的。 But it's not recommended
但不推荐
my_callback: CallbackFn = lambda s1, s2, i1, i2: <do the thing>
Obviously you're limited by the constraints of a lambda
(no statements etc)显然你受到
lambda
的限制(没有声明等)
This is quite easy to do with a no-op decorator.使用空操作装饰器很容易做到这一点。
from collections.abc import Callable
from typing import Any, TypeAlias, TypeVar
CallbackFn: TypeAlias = Callable[[str, str, int, int], None]
Any4ParamCallableT = TypeVar("Any4ParamCallableT", bound=Callable[[Any, Any, Any, Any], None])
def asCallbackFn(f: Any4ParamCallableT, /) -> CallbackFn:
"""No-op decorator to impart typing to the function being decorated"""
return f
@asCallbackFn
def my_callback(s1, s2, i1, i2):
return
Here's a deliberate attempt to use wrong types in the return and parameter values:这是故意在返回值和参数值中使用错误类型的尝试:
# mypy: Incompatible types in assignment (expression has type "None", variable has type "int") [assignment]
# mypy: Argument 1 to "my_callback" has incompatible type "int"; expected "str" [arg-type]
# mypy: Argument 2 to "my_callback" has incompatible type "int"; expected "str" [arg-type]
retval: int = my_callback(1, 2, 3, 4)
I don't really recommend trying to do what you're doing though, it's better to explicitly type each function. Among other things, you'll lose the ability to use keyword argument calling convention if you type things with Callable[[<type>, ...], ...]
(you can use a callback protocol, but then that forces you to name all your callback functions with the same named arguments).我真的不建议尝试做你正在做的事情,最好明确地键入每个 function。除此之外,如果你使用
Callable[[<type>, ...], ...]
内容,你将失去使用关键字参数调用约定的能力Callable[[<type>, ...], ...]
(您可以使用回调协议,但这会强制您使用相同的命名参数命名所有回调函数)。
You could use a decorator to do this你可以使用装饰器来做到这一点
decorator function:装饰师 function:
def annotate(callback):
def wrapper(fn):
print(fn)
annotations = callback.__dict__["__args__"]
for i, name in enumerate(fn.__code__.co_varnames):
fn.__annotations__[name] = annotations[i]
fn.__annotations__['return'] = annotations[-1]
return fn
return wrapper
To use it, simply do:要使用它,只需执行以下操作:
CallbackFn = Callable[[str, str, int, int], None]
@annotate(CallbackFn)
def my_callback(s1: str, s2: str, i1: int, i2: int) -> None:
pass
Hope this helps希望这可以帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.