如何正确输入包装函数?
How do I type correctly a wrapper function?
假设以下声明:
from typing import Callable, TypeVar
T = TypeVar('T')
def wrapper(fn: Callable[..., T]) -> Callable[..., T]:
...
def identity(a: T) -> T:
...
@wrapper
def w_wrapped(a: T) -> T:
...
@identity
def i_wrapped(a: T) -> T:
...
两个注解函数可以这样使用:
def apply(fn: Callable[[str], int]) -> int:
# types fine:
val1 = fn(i_wrapped(''))
# mypy complains: error: Argument 1 has incompatible type "T"; expected "str"
val2 = fn(w_wrapped(''))
return val1 + val2
Callable
类型有什么问题?我可以在 wrapper
声明中使用 Callable[..., Any]
而不是 Callable[..., T]
。但我觉得这部分违背了目的,我想声明,当你将包装器与 str
一起使用时,结果将是 str
,而不是任何东西。可能还有其他解决方法,但这是 mypy 的限制还是我的误解?
当你写 Callable[..., T] 时,我相信编辑器无法将“...”与“T”关联起来。
“apply”fn 期待一个 str,w_wrapped 返回一个 str,但这个过程发生在“wrapper”内部逻辑中,因为“...”与 T 无关,编辑器正在处理两个不同的T,例如 T_0 和 T_1。也许这就是导致类型不匹配的原因。
我认为这里可能有两件事:
其次,Callable[..., T]
太松了。具体来说,它的参数与其 return 值之间没有任何联系。结果,对于 @wrapper
,w_wrapped
变成了 Callable[..., T]
,对其参数没有约束,而 w_wrapped('')
的输出是一个未绑定的 T
,这无法传递给需要 str
.
的 fn
根据您的用例,您有多种选择,包括
def wrapper(fn: Callable[[U], T]) -> Callable[[U], T]:
for U = TypeVar('U')
,尽管我相信 mypy 错误会阻止此工作。 U
也可以是 T
def wrapper(fn: C) -> C:
C = TypeVar('C', bound=Callable)
。这没有 Any
的问题,因为你在 Callable
上 边界 所以你保留了类型签名。但是,它会限制您对 wrapper
的实施,而不是 type: ignore
假设以下声明:
from typing import Callable, TypeVar
T = TypeVar('T')
def wrapper(fn: Callable[..., T]) -> Callable[..., T]:
...
def identity(a: T) -> T:
...
@wrapper
def w_wrapped(a: T) -> T:
...
@identity
def i_wrapped(a: T) -> T:
...
两个注解函数可以这样使用:
def apply(fn: Callable[[str], int]) -> int:
# types fine:
val1 = fn(i_wrapped(''))
# mypy complains: error: Argument 1 has incompatible type "T"; expected "str"
val2 = fn(w_wrapped(''))
return val1 + val2
Callable
类型有什么问题?我可以在 wrapper
声明中使用 Callable[..., Any]
而不是 Callable[..., T]
。但我觉得这部分违背了目的,我想声明,当你将包装器与 str
一起使用时,结果将是 str
,而不是任何东西。可能还有其他解决方法,但这是 mypy 的限制还是我的误解?
当你写 Callable[..., T] 时,我相信编辑器无法将“...”与“T”关联起来。 “apply”fn 期待一个 str,w_wrapped 返回一个 str,但这个过程发生在“wrapper”内部逻辑中,因为“...”与 T 无关,编辑器正在处理两个不同的T,例如 T_0 和 T_1。也许这就是导致类型不匹配的原因。
我认为这里可能有两件事:
其次,Callable[..., T]
太松了。具体来说,它的参数与其 return 值之间没有任何联系。结果,对于 @wrapper
,w_wrapped
变成了 Callable[..., T]
,对其参数没有约束,而 w_wrapped('')
的输出是一个未绑定的 T
,这无法传递给需要 str
.
fn
根据您的用例,您有多种选择,包括
def wrapper(fn: Callable[[U], T]) -> Callable[[U], T]:
forU = TypeVar('U')
,尽管我相信 mypy 错误会阻止此工作。U
也可以是T
def wrapper(fn: C) -> C:
C = TypeVar('C', bound=Callable)
。这没有Any
的问题,因为你在Callable
上 边界 所以你保留了类型签名。但是,它会限制您对wrapper
的实施,而不是type: ignore