如何正确输入包装函数?
假设以下声明:
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
,而不是任何东西。可能还有其他解决方法,但这是我的限制还是我的误解?
Assume following declarations:
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:
...
The two annotated functions can be used like this:
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
What's wrong with the Callable
type? I can use Callable[..., Any]
instead of Callable[..., T]
in the wrapper
declaration. But I feel like this partially defeats the purpose, I would like to declare that when you use the wrapper with str
, the result would be str
, not just anything. There may be other workarounds too, but is this mypy limitation or my misunderstanding?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为这里可能发生两件事:
首先,mypy bug,请参阅 this 和 this
其次,
Callable[..., T] 太松散了。具体来说,它的参数和返回值之间没有任何联系。因此,使用
代码>.@wrapper
,w_wrapped
成为Callable[..., T]
,对其参数没有限制,并且w_wrapped('')
的输出是未绑定的T
,它无法传递给需要str
fn根据您的用例,您有多种选择,包括
U = TypeVar('U')
,尽管我相信 mypy bug 会阻止此工作。U
也可以是T
defwrapper(fn: C) -> C:
forC = TypeVar('C',bound=Callable)
。这不存在Any
的问题,因为您在Callable
上绑定,因此您保留了类型签名。但是,它会限制您对wrapper
的实现,缺少type:ignore
I think there may be two things going on here:
Firstly, a mypy bug, see this and this
Secondly,
Callable[..., T]
is too loose. Specifically, there's no connection between its argument and its return value. As a result, with@wrapper
,w_wrapped
becomes aCallable[..., T]
, with no constraint on its argument, and the output ofw_wrapped('')
is a unboundT
, which can't be passed tofn
which expects astr
.You have a number of options depending on your use case, including
def wrapper(fn: Callable[[U], T]) -> Callable[[U], T]:
forU = TypeVar('U')
, though I believe the mypy bugs stops this working.U
could also beT
def wrapper(fn: C) -> C:
forC = TypeVar('C', bound=Callable)
. This doesn't have the problem ofAny
because you're bounding onCallable
so you retain the type signature. However, it will limit your implementation ofwrapper
, short oftype: ignore
当您编写 Callable[..., T] 时,我相信编辑器无法将“...”与“T”关联起来。
“apply”fn 期望一个 str,w_wrapped 返回一个 str,但这个过程发生在“wrapper”内部逻辑内部,因为“...”与 T 无关,编辑器正在处理两个不同的 T,例如 T_0和T_1。也许这就是导致类型不匹配的原因。
When you write Callable[..., T], I believe the editor is not able to correlate "..." with "T".
"apply" fn is expecting a str, w_wrapped is returning a str, but this process is happening inside "wrapper" inner logic, since "..." is not relatable to T, the editor is dealing with two different T's, like T_0 and T_1. Maybe thats whats causing type mismatch.