如何根据参数类型声明返回类型



这个问题类似于Python类型:根据函数参数声明返回值类型,但差异很大,不适合注释。

我有以下功能:

T = TypeVar('T', dict, str)
def fun(t: T) -> T:
if t == dict:
return {"foo": "bar"}
else:
return "foo"

我希望能够这样称呼它:

a_string = fun(str)
a_dict = fun(dict)

Pylance在第二行抛出这个错误:

Expression of type "dict[str, str]" cannot be assigned to return type "T@fun"

最后一行的错误:

Expression of type "Literal['foo']" cannot be assigned to return type "T@fun"

根据这个答案,我应该能够做这样的事情:

T = TypeVar('T', dict, str)
def fun(t: Type[T]) -> T:
if t == dict:
return t({"foo": "bar"})
else:
return t("foo")

这消除了第二行的错误,但在最后一行引起了不同的错误:

No overloads for "__init__" match the provided arguments
Argument types: (Literal['foo'])

我研究了这个答案很长时间,终于能够使它发挥作用:

T = TypeVar('T', dict, str)
def fun(t: Callable[..., T]) -> T:
if t == dict:
return t({"foo": "bar"})
else:
return t("foo")

问题是我不明白为什么它有效。我不明白为什么其他人没有。

这个问题是我不明白为什么它能在中工作

最后一个有效,因为类型是可调用的。所以这里的类型表示fun接受某个东西,给定某个东西就会返回T,然后以类型的形式提供它。

我不明白为什么其他人不这么做。

第一个版本不起作用,因为->的左侧和右侧之间没有绑定。因此,您可以传递一个typevar,但不能指定左边的specific必须是右边的specific。换句话说,如果参数是dict,那么根据签名,返回类型不必是dict,而是typevar指定的类型(这有点令人困惑,因为两者中都出现了相同的符号T。然而,T在这里的意思是"…之一"(。

第二个版本不起作用,因为就类型检查器而言,return表示您也在返回类型。

您也可以在此处使用typing.overload

from typing import TypeVar, Type, overload, Callable

T = TypeVar('T')

@overload
def fun(t: Type[dict]) -> dict:
...

@overload
def fun(t: Type[str]) -> str:
...

def fun(t: Callable[..., T]) -> T
if t == dict:
return t({"foo": "bar"})
else:
return t("foo")

这应该允许fun(dict)fun(str),但不允许使用不同类型的调用,同时也确保fun确实返回作为参数传递的类型的值。

最新更新