Python 如何使用默认函数键入zip_
如何键入此函数,根据某个函数来压缩映射值Python 如何使用默认函数键入zip_,python,type-hinting,Python,Type Hinting,如何键入此函数,根据某个函数来压缩映射值 K = TypeVar("K") U = TypeVar("U") V = TypeVar("V") W = TypeVar("W") def zip_with( u: Mapping[K, U], v: Mapping[K, V], f: Callable[[U, V], W] = lambda u, v: (u, v) ) -> Mapp
K = TypeVar("K")
U = TypeVar("U")
V = TypeVar("V")
W = TypeVar("W")
def zip_with(
u: Mapping[K, U],
v: Mapping[K, V],
f: Callable[[U, V], W] = lambda u, v: (u, v)
) -> Mapping[K, W]:
return {k: f(u[k], v[k]) for k in u}
我要走了
utils/misc.py:66:错误:参数“f”的默认值不兼容(默认值的类型为“Callable[[U,V],Tuple[U,V]]”,参数的类型为“Callable[[U,V],W]”)
utils/misc.py:66:错误:返回值类型不兼容(获取“Tuple[U,V]”,应为“W”)
Afaik mypy无法通过默认参数推断类型签名,但重载可以帮助。然而,我看不出你如何在不丢失某个类型安全性的情况下做到这一点,因为如果f
的默认值不是函数,那么就无法创建W
例如
@overload
def zip_with(u: Mapping[K, U], v: Mapping[K, V]) -> Mapping[K, Tuple[U, V]]:
...
@overload
def zip_with(
u: Mapping[K, U],
v: Mapping[K, V],
f: Callable[[U, V], W]
) -> Mapping[K, W]:
...
def zip_with(
u: Mapping[K, U],
v: Mapping[K, V],
f: Optional[Callable[[U, V], W]] = None
) -> Mapping[K, W]:
if f is None:
return {k: (u[k], v[k]) for k in u}
return {k: f(u[k], v[k]) for k in u}
给予
f
的默认值是lambda u,v:(u,v)
,它的返回值为Tuple[无论u是什么,无论v是什么]
,但是您在它们的类型提示中指定可调用[[u,v],W]
返回值应该是W
如果
Tuple[U,V]
属于W
类型,那么你对W
的定义应该证明这一点W=Tuple[U,V]
我不理解你所说的“你对W的定义应该证明这一W=Tuple[U,V]”。我不确定这是否可能,因为返回类型中的W
可能是由输入中的W
绑定的,但如果没有f
,则根本不绑定,因此我们不能符合不存在的类型>返回类型可能是由输入@joel中的W绑定的,我不明白你的意思,正如您当前将W全局定义为W=TypeVar(“W”)
。这个定义与Tuple[U,V]
您从默认值lambda U,V:(U,V)
返回的Tuple[U,V]相矛盾,我认为它并不矛盾,但它限制了它,并且以一种有效的方式,就像我将lambda
作为参数传递一样,我希望mypy推断W
是Tuple[U,V]
在这种情况下,scala编译中的等效代码很好,这不是一个非常令人满意的答案,但通常在键入像这样的棘手内容时,我会在实际实现函数中键入一个Any
或#键入:ignore
,然后编写大量的单元测试来证明它实际上遵守了类型重载指定的契约。@Samwise我可以通过@重载
并在实现签名中将W
设置为Any
,同时保持lambda
默认值来实现非常接近的效果
utils/misc.py:81: error: Value expression in dictionary comprehension has incompatible type "Tuple[U, V]"; expected type "W"